我如何同时等待两件或更多件事(不同类型)?就像在事件循环中一样:
while(true) {
Letter msg1 = await WaitForLetter();
//read msg1 and reply.
SMS msg2 = await WaitForSMS();
//read msg2 and reply
}
看起来并不正确。这两条消息最终会相互阻塞?
答案 0 :(得分:4)
我认为您最好的选择是使用Microsoft的Reactive Framework(NuGet“Rx-Main”)。它与Tasks非常吻合。
以下是您需要的代码:
var subscription1 =
Observable
.FromAsync(WaitForLetter)
.Repeat()
.Subscribe(msg1 =>
{
//read msg1 and reply.
});
var subscription2 =
Observable
.FromAsync(WaitForSMS)
.Repeat()
.Subscribe(msg2 =>
{
//read msg2 and reply
});
两者彼此独立运行,并且都是异步运行。
要阻止它们运行,只需执行以下操作:
subscription1.Dispose();
subscription2.Dispose();
如果你真的希望它们像事件循环那样运行,那么消息都在同一个线程上,相互穿插,那么你可以这样做:
var eventLoopScheduler = new EventLoopScheduler();
var subscription1 =
Observable
.FromAsync(WaitForLetter)
.Repeat()
.ObserveOn(eventLoopScheduler)
.Subscribe(msg1 =>
{
//read msg1 and reply.
});
var subscription2 =
Observable
.FromAsync(WaitForSMS)
.Repeat()
.ObserveOn(eventLoopScheduler)
.Subscribe(msg2 =>
{
//read msg2 and reply
});
你有更多的清理工作,但这可以很好地处理:
var subscriptions = new CompositeDisposable(
subscription1,
subscription2,
eventLoopScheduler);
//then later
subscriptions.Dispose();
答案 1 :(得分:3)
目前,您的代码将等待每个方法依次完成。如果要发送每条消息,然后在最后等待两个消息,则可以使用Task.WaitAll
方法(假设您的方法返回Task<T>
个对象。
while(true) {
Task<Letter> msgTask1 = WaitForLetter();
Task<SMS> msgTask2 = WaitForSMS();
Task.WaitAll(msgTask1, msgTask2);
}
然后,您可以使用Result
属性获取每项任务的结果(再次假设您的方法返回Task<T>
:
Letter msg1 = msgTask1.Result;
SMS msg2 = msgTask2.Result;
当然,这一切都假设WaitForLetter
和WaitForSMS
的实施是独立的,不会相互阻挡。
如果您只想等待任何任务完成,您可以将`Task.WaitAny'用于同一目的。这将返回已完成的任务的索引,以便您知道哪一个已完成。
while(true) {
Task<Letter> msgTask1 = WaitForLetter();
Task<SMS> msgTask2 = WaitForSMS();
var finishedTask = Task.WaitAny(msgTask1, msgTask2);
}