我处于这种情况: 许多客户端可以向控制器发送命令,控制器必须按顺序处理每个命令,并将响应发送回每个客户端。客户端异步“等待”响应。
所以,到目前为止,当我从客户端收到命令时,我将命令排入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。
答案 0 :(得分:1)
您可以使用BlockingCollection代替队列 - 经典生产者消费者模式,查看example in MSDN documentation。这将消除计时器的使用,因为queue.Take()
将阻塞,直到队列中有一个项目为止。
答案 1 :(得分:1)
不要只将要发送的项目排入队列。包括允许消费者通知生产者的数据。例如,您可以包含一个TaskCompletionSource
,该await TaskCompletionSource.Task
设置为由消费者在适当的点完成。制作人可以{{1}}。