在SignalR集线器中应使用异步还是非异步方法?

时间:2019-07-24 06:53:13

标签: c# asp.net-mvc asp.net-core async-await signalr

我在Hub部分有以下SignalR类,在这里定义了所有与连接有关的方法:

public override Task OnConnected()
{
    // here I cannot call this, and need to convert this method async
     await AddToGroup("stockGroup");
    //

    string name = Context.User.Identity.Name;
    _connections.Add(name, Context.ConnectionId);
    return base.OnConnected();
}

public async Task AddToGroup(string groupName)
{
    await Groups.Add(Context.ConnectionId, groupName);
    await Clients.Group(groupName).SendAsync("Send", $"{Context.ConnectionId} joined");
}

我看了许多有关这些连接方法(和其他集线器方法)的示例,发现其中一些使用async方法,而另一些则没有。在上面的示例中,我需要将OnConnected()方法转换为async才能调用AddToGroup()方法。当然,相反的情况也可以,但是我不确定哪个更好。因此,对于async中的所有方法,我应该使用Hub方法还是非异步方法?任何帮助,将不胜感激。

更新1:转换后的方法(异步)。

public override async Task OnConnected()
{        
    await AddToGroup("stockGroup");

    string name = Context.User.Identity.Name;
    _connections.Add(name, Context.ConnectionId);
    return base.OnConnected();
}


更新2:

public override async Task OnConnected()
{
    // #1 There is no async method in "Microsoft.AspNet.SignalR" library. 
    //await Groups.AddToGroupAsync(Context.ConnectionId, "SignalR Users");  

    // #2 I just have sync version of "AddToGroupAsync()" and used it
    await Groups.Add(Context.ConnectionId, "SignalR Users");

    /* #3 I think there is no need to use this custom method in the Hub. 
    Because the same method is already exist in the IGroupManager interface */
    //await AddToGroup("jiraGroup");        

    string name = Context.User.Identity.Name;
    _connections.Add(name, Context.ConnectionId);

    // #4 Here also the same problem and I used sync version of OnConnected()
    //await base.OnConnectedAsync();
    await base.OnConnected();
}

2 个答案:

答案 0 :(得分:2)

如果在方法内部需要async,只需添加awaitasync是编译器生成异步状态机的标记。

should I use async-如果需要等待,请使用。

如果您不需要await,只需返回没有async的任务即可。在这种情况下,您可以避免创建状态机。

也请阅读Stephen Toub的Async/Await FAQ

  

当您使用“ async”关键字标记方法时,您实际上是在说   编译器有两件事:

     
      
  1. 您正在告诉编译器您希望能够使用   方法内的“ await”关键字(如果需要,可以使用await关键字   并且仅当其所在的方法或lambda被标记为异步时)。这样做   因此,您要告诉编译器使用状态来编译方法   机器,这样该方法将能够挂起然后继续   在等待点异步进行。

  2.   
  3. 您要告诉编译器“抬起”   方法的结果或可能发生的任何异常   返回类型。对于返回Task或Task的方法,此   表示在其中未处理的任何返回值或异常   该方法将存储到结果任务中。对于返回的方法   无效,这意味着任何异常都会传播到呼叫者的   通过当时最新的“ SynchronizationContext”上下文   方法的初始调用。

  4.   

答案 1 :(得分:1)

您应在Await中使用 Async 方法并返回Task。

异步具有病毒性,因此您应该避免异步无效

 public async void MethodAsync()
    {
        var result = await SendAsync();
        DoSomething(result);
    }

 public async Task MethodAsync()
    {
        var result = await SendAsync();
        DoSomething(result);
    }

@davidfowl here

有一些很棒的异步指南

更新:删除退货

public override async Task OnConnected()
{        
    await AddToGroup("stockGroup");

    string name = Context.User.Identity.Name;
    _connections.Add(name, Context.ConnectionId);
    await base.OnConnected();
}