我有一个应用程序正在使用.net 4.0中的任务处理FIFO队列中的项目。
我是.net中的TPL和任务的新手,并且想知道我的问题是否有一个简单的解决方案:
任务中的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
对象结束?
答案 0 :(得分: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
的一个示例 - 您可能希望根据自己的需要对其进行优化。