线程和任务等待之间的通信

时间:2014-07-09 07:59:08

标签: c# multithreading asynchronous task messaging

我处于这种情况: 许多客户端可以向控制器发送命令,控制器必须按顺序处理每个命令,并将响应发送回每个客户端。客户端异步“等待”响应。

所以,到目前为止,当我从客户端收到命令时,我将命令排入ConcurrentQueue并运行一个Task,其中客户端异步等待响应。控制器有一个始终在ConcurrentQueue上搜索新命令的线程,取第一个,处理它并应该响应发送者(客户端),但这里是我被卡住的地方,因为我不知道如何制作控制器完全响应发送命令的客户端(控制器有一个包含许多命令的队列,但不知道是谁发送了它们)。

我的想法: 将一条消息从一个Thread直接发送到一个带有响应对象的Task会很棒。有可能吗?

我的代码:

private ConcurrentQueue<byte[]> sendBuffer;

public async Task<IViewAppMessage> sendCommandAsync(byte[] command)
{                              
     sendBuffer.Enqueue(command);

      return await Task.Run<IViewAppMessage>(() =>
      {
            //Pool for a response
      }           
}

/* Method executed within a Timer worker thread */
private void senderPool(object stateInfo)
{
    try
    {
        //Stop timer
        senderTimer.Change(Timeout.Infinite, Timeout.Infinite);
        //Take command from FIFO
        byte[] commandToSend;
        if(sendBuffer.TryDequeue(out commandToSend))
        {
            //Send command to camera
            cameraSender.Send(commandToSend, commandToSend.Length);                    
            byte[] response = cameraListener.Receive(ref endPoint);

            IViewAppMessage returnMessage = processResponse(response);

            //Notify the response. HOW?????????????  
        }                
    }
    catch 
    {
        //Notify Error
    }
    //In any case, timer restarts
    finally
    {
        try
        {
            //Arrancamos timer
            senderTimer.Change(100, Timeout.Infinite);
        }
        catch 
        { 
            //Fatal error
        }
    }
}

谢谢!

修改

我知道我可以使用带有所有响应的BlockingCollection,所以当发送者收到响应时,它会在集合中分配它,然后客户端轮询一个响应,但是使用这种方法我应该给每个客户端一个ID (或类似的东西)检查带有ID的响应。这可能是一个解决方案,但我想知道是否有可能通过响应直接向任务发送消息,因为我认为类似的东西会是一个更好的方法,因为不需要让客户轮询也不需要他们不是并发ID。

2 个答案:

答案 0 :(得分:1)

您可以使用BlockingCollection代替队列 - 经典生产者消费者模式,查看example in MSDN documentation。这将消除计时器的使用,因为queue.Take()将阻塞,直到队列中有一个项目为止。

答案 1 :(得分:1)

不要只将要发送的项目排入队列。包括允许消费者通知生产者的数据。例如,您可以包含一个TaskCompletionSource,该await TaskCompletionSource.Task设置为由消费者在适当的点完成。制作人可以{{1}}。