2014-09-26 4 views
2

У меня есть приложение, которое обрабатывает элементы в очереди FIFO, используя Tasks в .net 4.0.Использование async-сокета в задачах

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

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

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

EDIT Добавлен некоторый код:

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?

+0

Вероятно, Wait() в корневом потоке/задаче. Можете ли вы показать, какой код у вас есть? – MatthewMartin

+0

Опубликовать то, что у вас есть. –

+0

Что такое «AsyncSocket»? Если 'SendData()' асинхронно, то вам, вероятно, нужно «ждать» его. – svick

ответ

2

Если я правильно понимаю, вы хотите ждать на задаче получает данные, но вы в настоящее время ожидания на задачу, которая посылает данные. Один из способов сделать это было бы использовать конструкцию как 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 - вы, вероятно, хотите усовершенствовать его в соответствии с вашими потребностями.

+0

Эй, ты не знал бы это: это сработало! Удивительно, спасибо! – oGJo

+0

Обратите внимание, что при синхронизации потоков следует соблюдать осторожность. Например, если 'DoSomeWork' отправляет две отдельные строки данных, вы хотите вызвать' Set' только после того, как все данные будут получены, иначе вторая задача начнется до того, как будет завершена первая. –

Смежные вопросы