C# 使用异步/等待、接收和LINQ进行异步消息处理

C# 使用异步/等待、接收和LINQ进行异步消息处理,c#,.net,linq,async-await,system.reactive,C#,.net,Linq,Async Await,System.reactive,我将反应式扩展与async/await结合使用,以简化套接字协议的实现。当特定消息到达时,必须执行一些操作(例如,向每个“ping”消息发送“pong”),还有一些方法,我们必须异步等待一些特定的响应。以下示例说明了这一点: private Subject<string> MessageReceived = new Subject<string>(); //this method gets called every time a message is received

我将反应式扩展与async/await结合使用,以简化套接字协议的实现。当特定消息到达时,必须执行一些操作(例如,向每个“ping”消息发送“pong”),还有一些方法,我们必须异步等待一些特定的响应。以下示例说明了这一点:

private Subject<string> MessageReceived = new Subject<string>();

//this method gets called every time a message is received from socket
internal void OnReceiveMessage(string message)
{
    MessageReceived.OnNext(message);
    ProcessMessage(message);
}

public async Task<string> TestMethod()
{
    var expectedMessage = MessageReceived.Where(x => x.EndsWith("D") && x.EndsWith("F")).FirstOrDefaultAsync();
    await SendMessage("ABC");

    //some code...

    //if response we are waiting for comes before next row, we miss it
    return await expectedMessage;
}
private Subject MessageReceived=new Subject();
//每次从套接字接收消息时,都会调用此方法
接收消息时内部无效(字符串消息)
{
MessageReceived.OnNext(message);
ProcessMessage(消息);
}
公共异步任务TestMethod()
{
var expectedMessage=MessageReceived.Where(x=>x.EndsWith(“D”)和&x.EndsWith(“F”).FirstOrDefaultAsync();
等待发送消息(“ABC”);
//一些代码。。。
//如果我们等待的响应在下一行之前到达,我们将错过它
返回等待预期消息;
}
TestMethod()将“ABC”发送到套接字,并在收到例如“DEF”时继续(在此之前可能还有其他消息)


这几乎有效,但有一个比赛条件。这段代码似乎在
return wait expectedMessage之前不会侦听消息这是一个问题,因为有时消息会在这之前到达。

FirstOrDefaultAsync
在这里不能很好地工作:它在
等待
行之前不会订阅,这会给您留下竞争条件(正如您所指出的)。以下是如何替换它:

    var expectedMessage = MessageReceived
        .Where(x => x.EndsWith("D") && x.EndsWith("F"))
        .Take(1)
        .Replay(1)
        .RefCount();

    using (var dummySubscription = expectedMessage.Subscribe(i => {}))
    {
        await SendMessage("ABC");

        //Some code... goes here.

        return await expectedMessage;
    }

.Replay(1)
确保新订阅获取最新条目(假设存在)。不过,它只在有订阅者监听的情况下工作,因此
dummySubscription

您的意思是pong在等待
预期消息时未被发送
?在这种情况下,您应该在
OnReceiveMessage
中处理
ping
消息,而不将其与
MessageReceived.OnNext()
一起存储,事实上,第一部分没有包含在示例中。很好用。在ProcessMessages()方法中,我发送pong以响应ping消息,但问题是在异步方法中等待特定事件(从套接字接收的消息)