编程语言
首页 > 编程语言> > c# – 在异步方法中使用时,SignalR不会返回

c# – 在异步方法中使用时,SignalR不会返回

作者:互联网

我不确定这是一个SignalR问题还是async / await问题.当我的客户端应用程序(WPF)启动时,它会进行一些初始化: –

public async void Initialise()
{
    // Get data from the server - async, as it may be long-running.
    var data = await _hubProxy.Invoke<FooData>("Method1");

    _dataProcessor.ProcessData(data);
}

_dataProcessor是一个帮助程序类,它使用传递给它的数据执行一些操作,然后在某些时候使用类似于以下行的方法调用不同的服务器方法:

var moreData = _hubProxy.Invoke<BarData>("Method2").Result;

helper类中的所有代码都不是异步的.

第一个服务器调用(在Initialise()中)工作正常 – 它获取数据并将其传递给辅助类.这种方法在调用之前没有问题 – 它被调用但永远不会返回,并且线程永远不会超过这一行.我在服务器方法中放置了一个断点,可以确认它正在被调用并返回一个值,但由于某种原因,这并没有回到客户端.

奇怪的是,如果我在Initialise()方法中取出async / await关键字,一切正常.我究竟做错了什么?为什么这些关键字会影响帮助程序类中的同步代码?

(我意识到你通常不应该使用异步void,但是因为Initialise()方法是“火上浇油而忘记”,我认为在这种情况下没关系).

解决方法:

此行导致UI线程出现死锁:

var moreData = _hubProxy.Invoke<BarData>("Method2").Result;

使ProcessData成为异步方法并等待其中的_hubProxy.Invoke:

var moreData = await _hubProxy.Invoke<BarData>("Method2");

然后,在您的Initialise中等待_dataProcessor.ProcessData:

await _dataProcessor.ProcessData(data);

确保不要在其他任何地方使用.Result或.Wait.

另一种解决方法就是这样:

public async void Initialise()
{
    // Get data from the server - async, as it may be long-running.
    var data = await _hubProxy.Invoke<FooData>("Method1").ConfigureAwait(false);

    _dataProcessor.ProcessData(data);
}

注意ConfigureAwait(false).在这种情况下,await之后的延续将在非UI线程上发生.这将消除死锁,但这不是一个理想的解决方案,而是一种解决方法.此外,您的逻辑可能需要在UI线程上继续,UI访问或一些线程安全问题.

最好的解决方案是同时使用ConfigureAwait(false)(如果可能)并避免使用.Result或.Wait进行阻塞.

标签:c,async-await,signalr,signalr-client
来源: https://codeday.me/bug/20190624/1279544.html