在SignalR 2.0 OnReceived处理程序中调用等待的正确方法

时间:2014-04-16 15:45:35

标签: c# asynchronous signalr .net-4.5 async-await

我正在使用带有PersistentConnection(而不是集线器)的SignalR 2.0.1,目前我的默认非常简单的OnReceived处理程序如下所示:

protected override Task OnReceived(IRequest request, string connectionId, string data)
{
    return Connection.Broadcast(data);
}

我想为这个处理程序添加一些I / O绑定代码,比如访问另一台机器上的数据库。当然我希望一切都是异步的,我不想阻止线程,所以我希望使用像EF6的db.SaveChangesAsync()这样的异步风格(而不是常规阻塞db.SaveChanges)。

我将db.SaveChangesAsync()添加到处理程序中,但我也需要await。所以我还在处理程序中添加了一个async修饰符,但这导致了我的返回值错误 - 我再也无法返回Connection.Broadcast(data)

这是我最终得到的:

protected override async Task OnReceived(IRequest request, string connectionId, string data)
{
    // some EF code here..

    await db.SaveChangesAsync();

    // the original return changes into this?
    await Connection.Broadcast(data);
}

这是正确的方法吗?因为我有一种感觉,我正在滥用这种模式。


顺便说一下,如果我理解正确的话,SignalR的当前版本是完全异步的。像here描述的旧版本有两个处理程序 - 一个是同步的,一个是异步的(带有Async后缀)。

2 个答案:

答案 0 :(得分:3)

是的,这是一种完全合理的方式。为什么你觉得你可能会滥用这种模式?

这样想:

  • 返回void的同步方法对应于返回Task的异步方法。同样,
  • 返回T的同步方法对应于返回Task<T>的异步方法。

这就是你不能做的原因

protected override async Task OnReceived(IRequest request, string connectionId, string data)
{
    return Connection.Broadcast(data);
}

,因为async关键字和return语句会指示返回Task<Task>的方法。

您可以做的是完全删除您的上一个await。它所要做的就是创建一个空的延续(因为它基本上是说&#34;当广播完成后,在广播之后运行代码,直到结束大括号&#34;)。或者,如果您愿意,可以保持一致性。

答案 1 :(得分:3)

我的博客上有async intro,您可能会觉得有帮助。

Task个实例代表“未来”。所以当你这样做时:

protected override Task OnReceived(IRequest request, string connectionId, string data)
{
  return Connection.Broadcast(data);
}

您说“OnReceived完成后Connection.Broadcast(data)已完成”。这实际上与:

相同
protected override async Task OnReceived(IRequest request, string connectionId, string data)
{
  await Connection.Broadcast(data);
}

这说“OnReceived将(异步)等待Connection.Broadcast(data)完成,然后OnReceived将完成。” 没有 asyncawait,效率稍高一些,但它们的语义基本相同。

所以,是的,这段代码是正确的:

protected override async Task OnReceived(IRequest request, string connectionId, string data)
{
  // some EF code here..
  await db.SaveChangesAsync();

  await Connection.Broadcast(data);
}