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