当我在Task.Wait()中使用阻塞代码时,在等待Rx查询的async方法时,我遇到了一个死锁。
这就是一个例子:
public void BlockingCode()
{
this.ExecuteAsync().Wait();
}
public async Task ExecuteAsync()
{
await this.service.GetFooAsync().ConfigureAwait(false);
//This is the RX query that doesn't support ConfigureAwaitawait
await this.service.Receiver
.FirstOrDefaultAsync(x => x == "foo")
.Timeout(TimeSpan.FromSeconds(1));
}因此,我的问题是,在可访问的ConfigureAwait上是否有任何等价的IObservable来确保在同一个SynchronizationContext上不恢复延续。
发布于 2015-05-17 17:55:34
你必须理解“等待观察”意味着什么。看看这。所以,在语义上,您的代码
await this.service.Receiver
.FirstOrDefaultAsync(x => x == "foo")
.Timeout(TimeSpan.FromSeconds(1));等于
await this.service.Receiver
.FirstOrDefaultAsync(x => x == "foo")
.Timeout(TimeSpan.FromSeconds(1))
.LastAsync()
.ToTask();(请注意,这里存在某种冗余,调用FirstOrDefaultAsync和LastAsync,但这不是问题)。
因此,您就可以完成任务(如果可用的话,还可以增加一个CancellationToken )。您现在可以使用ConfigureAwait了。
发布于 2015-05-15 17:57:50
ConfigureAwait与服务生本身没有直接关系,相反,它是TPL的一个功能,可以配置Task应该如何完成。这是有问题的,因为这个TPL方法不返回一个新的Task,所以您不能将它转换成可观察的Task。
Rx本身基本上是自由线程的。您可以使用比Tasks更精细的控件来控制订阅和事件期间使用的线程-有关以下内容的更多信息:ObserveOn和SubscribeOn -正在做工作的地方
很难修复您的代码,因为您没有提供一个小型但完整的工作示例--但是,Rx中内置的函数不会尝试将其配置到特定的线程,除非您特别告诉它们使用上面的操作符之一。
如果将像Observable.FromAsync这样的运算符组合起来,将Task转换为可观察的,则可以使用Observable.SubscribeOn(Scheduler.Default)从当前SynchronizationContext启动Task。
下面是一个可玩的要点(为LINQPad设计,使用nuget包rx运行):https://gist.github.com/james-world/82c3cc39babab7870f6d
https://stackoverflow.com/questions/30261847
复制相似问题