Использование асинхронного сокета в задачах

У меня есть приложение, которое обрабатывает элементы в очереди FIFO с помощью задач в.net 4.0.

Я новичок в TPL и Задачах в.net, и мне было интересно, есть ли простое решение моей проблемы:

Делегат Action в Задаче назначается методу, который отправляет и получает данные в асинхронном сокете. У меня проблема в том, что Задача заканчивается "преждевременно". Как мне сказать Задаче подождать, пока все коммуникации не будут завершены, прежде чем обрабатывать следующий элемент в очереди?

Одним из решений является переключение на использование синхронного сокета, но я надеялся, что есть способ сделать это с помощью асинхронного сокета.

РЕДАКТИРОВАТЬ Добавлен код:

class Program
{
    private BlockingCollection<string> myQueue;
    private CancellationTokenSource cancellationSignalForConsumeTask;
    private CancellationTokenSource cancellationSignalForProcessCommandTask;
    private AsyncSocket mySocket;

    public void Main(string[] args)
   {
       mySocket = new mySocket();
       myscoket.ReceiveData += mySocket_ReceiveData;

       cancellationSignalForConsumeTask = new CancellationTokenSource();
       Task listenerTask = Task.Factory.StartNew((obj) => Consume(),
                                                          cancellationSignalForConsumeTask.Token,
                                                          TaskCreationOptions.LongRunning);

        while (true)
        {}
   }

    private void Consume()
    {
       while (!myQueue.IsCompleted )
            {
                string _item = myQueue.Take();

                cancellationSignalForProcessCommandTask = new CancellationTokenSource();
                Task t = new Task(() => 
                    {
                        cancellationSignalForProcessCommandTask.Token.ThrowIfCancellationRequested();
                        DoSomeWork(_item);
                    }, cancellationSignalForProcessCommandTask.Token, TaskCreationOptions.LongRunning);

                t.Start();
                t.Wait();
            }
    }

    private void DoSomeWork(string _item)
    {
       mySocket.SendData("Data to server that could take a long time to process")
    }

    private void mySocket_ReceiveData(string dataFromServer)
    {
        string returnMessage = dataFromServer;

        //I want the Task to end here...

    }
}

Проблема в том, что задача заканчивается, когда DoSomeWork() метод завершается (и я понимаю, почему), есть ли способ, которым я могу вручную сказать Задача завершить через CancellationTokenSource объект может быть?

1 ответ

Решение

Если я правильно понимаю, вы хотите дождаться выполнения задачи, которая получает данные, но в настоящее время вы ожидаете выполнения задачи, которая отправляет данные. Один из способов сделать это - использовать такую ​​конструкцию, как AutoResetEvent:

private AutoResetEvent autoResetEvent = new AutoResetEvent(false);

private void Consume()
{
   while (!myQueue.IsCompleted )
        {
            string _item = myQueue.Take();

            cancellationSignalForProcessCommandTask = new CancellationTokenSource();
            Task t = new Task(() => 
                {
                    cancellationSignalForProcessCommandTask.Token.ThrowIfCancellationRequested();
                    DoSomeWork(_item);
                }, cancellationSignalForProcessCommandTask.Token, TaskCreationOptions.LongRunning);

            t.Start();

            // Wait for data to be received.
            // This line will block until autoResetEvent.Set() is called.
            autoResetEvent.WaitOne();
        }
}

private void mySocket_ReceiveData(string dataFromServer)
{
    string returnMessage = dataFromServer;

   // Notify other threads that data was received and that processing can continue.
   autoResetEvent.Set();
}

Это только пример использования AutoResetEvent - вы, вероятно, захотите улучшить его в соответствии с вашими потребностями.

Другие вопросы по тегам