C# 在一个循环中等待两件事?

C# 在一个循环中等待两件事?,c#,asynchronous,task,C#,Asynchronous,Task,我怎么能同时等待两件或两件以上的事情(不同类型的)?就像在事件循环中一样: while(true) { Letter msg1 = await WaitForLetter(); //read msg1 and reply. SMS msg2 = await WaitForSMS(); //read msg2 and reply } 这看起来不对。这两条消息最终会互相阻塞?目前,您的代码将依次等待每个方法完成。如果希望发送每条消息,然后在最后等待这两条消息,则可以

我怎么能同时等待两件或两件以上的事情(不同类型的)?就像在事件循环中一样:

while(true) {
    Letter msg1 = await WaitForLetter();
    //read msg1 and reply.
    SMS msg2 = await WaitForSMS();
    //read msg2 and reply
}

这看起来不对。这两条消息最终会互相阻塞?

目前,您的代码将依次等待每个方法完成。如果希望发送每条消息,然后在最后等待这两条消息,则可以使用该方法(假设您的方法返回
Task
对象)

while(true) {
    Task<Letter> msgTask1 = WaitForLetter();
    Task<SMS> msgTask2 = WaitForSMS();

    Task.WaitAll(msgTask1, msgTask2);
}
当然,这一切都假设
WaitForLetter
WaitForSMS
的实现是独立的,不会相互阻塞

如果您只想等待任何任务完成,您可以使用to to More the end。这将返回已完成任务的索引,以便您知道哪个任务已完成

while(true) {
    Task<Letter> msgTask1 = WaitForLetter();
    Task<SMS> msgTask2 = WaitForSMS();

    var finishedTask = Task.WaitAny(msgTask1, msgTask2);
}
while(true){
任务msgTask1=WaitForLetter();
任务msgTask2=WaitForSMS();
var finishedTask=Task.WaitAny(msgTask1,msgTask2);
}

我认为您最好的选择是使用Microsoft的反应式框架(NuGet“Rx Main”)。它可以很好地处理任务

以下是您需要的代码:

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();

为什么你需要while(真的)在他的代码中,可能有更多的代码他没有发布。相关部分是
WaitAll
。但问题是,我可能一小时收到一条短信,但一个月只有一封信。所以我不能等所有的。我想等任何一条。我不确定如何做,当任务类型不同时,etc@someoneelse那你真走运有一种方法可以做到这一点,等待任何任务完成后再继续。你必须在任务完成之前添加一些验证,并确保不会遇到问题,但它是可用的。谢谢。task.WaitAny对不同类型的任务有效吗?例如,我可以将一个任务和一个任务放入任务[]数组?我想我必须创建一个任务数组,然后再把它转换成正确的类型(我是C++程序员,所以不太熟悉C变量数组)。您可以使用
WaitAll
WaitAny
,但除非每条短信都有一个字母,否则为什么要将它们放在同一个无限循环中?您可以将它们放在两个while循环中…无限循环中如果这里真的需要事件循环,那么RX确实需要并依靠代码解决方案来使用。@vittor-对不起,您能解释一下吗明白你所说的“需要并依靠代码解决方案来使用”是什么意思这看起来很干净。C语言世界里的人比C++更接近于异步。我有点嫉妒。我们最终会在下一个C++标准中等待和协同工作。很少有C++程序员知道如何使用等待。所以这就是为什么我最后问了如何使用C等待。我希望我们能得到一些好的框架。AR到LINQ和RX,在C++中建立在协程序的顶部。但是我们可能需要等待几年。@ Enigmativity是一个错误:“代码代码很好,很精益”。
var subscriptions = new CompositeDisposable(
    subscription1,
    subscription2,
    eventLoopScheduler);

//then later

subscriptions.Dispose();