在任务中使用异步套接字

时间:2014-09-26 17:20:22

标签: c# .net multithreading task-parallel-library task

我有一个应用程序正在使用.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对象结束?

1 个答案:

答案 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的一个示例 - 您可能希望根据自己的需要对其进行优化。