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

本文关键字:等待 调用 方法 程序 SignalR OnReceived 处理 | 更新日期: 2023-09-27 17:58:42

我正在使用带有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 的当前版本是完全异步的。像这里描述的旧版本有两个处理程序 - 一个同步和一个异步(带有Async后缀(。

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

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

可以这样想:

  • 返回 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。它所做的只是创建一个空的延续(因为它本质上是说"广播完成后,在广播之后运行代码,直到结尾大括号"(。或者,如果您愿意,可以将其保留以保持一致性。

我的博客上有一个async介绍,您可能会觉得有帮助。

Task实例代表"未来"。因此,当您执行此操作时:

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

你是说"OnReceivedConnection.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);
}