为什么任务永远等待?:
var task = Observable .FromEventPattern<MessageResponseEventArgs>(communicator,"PushMessageRecieved") .Where(i => i.EventArgs.GetRequestFromReceivedMessage().Name == requestName) .Select(i => i.EventArgs) .RunAsync(System.Threading.CancellationToken.None) .ToTask(); task.Wait();
我知道“PushMessageRecieved”被解雇了;我可以在Select lambda上设置一个断点并点击它.但task.Wait()永远不会移动.
更好的更新:FirstAsync()是我正在寻找的:
public static Task<MessageResponseEventArgs> HandlePushMessageRecievedAsync(this ICommunicator communicator,RequestName requestName) { if (communicator == null) return Task.FromResult<MessageResponseEventArgs>(null); var observable = GetCommunicatorObservableForPushMessageReceived(communicator); return observable .Where(i => i.GetRequestFromReceivedMessage().Name == requestName) .Select(i => i) .FirstAsync() .ToTask(); }
其中GetCommunicatorObservableForPushMessageReceived()是:
static IObservable<MessageResponseEventArgs> GetCommunicatorObservableForPushMessageReceived(ICommunicator communicator) { if (communicatorObservableForPushMessageReceived == null) { communicatorObservableForPushMessageReceived = Observable .FromEventPattern<MessageResponseEventArgs>(communicator,"PushMessageRecieved") .Where(i => !IsPrevIoUsMessage(i.EventArgs.GetRequestFromReceivedMessage().EventId)) .Select(i => i.EventArgs); } return communicatorObservableForPushMessageReceived; }
更新:这有点可怕(但它确实有效):
public static Task<MessageResponseEventArgs> HandlePushMessageRecievedAsync(this ICommunicator communicator,RequestName requestName) { if (communicator == null) return Task.FromResult<MessageResponseEventArgs>(null); var completionSource = new TaskCompletionSource<MessageResponseEventArgs>(); Observable .FromEventPattern<MessageResponseEventArgs>(communicator,"PushMessageRecieved") .Where(i => i.EventArgs.GetRequestFromReceivedMessage().Name == requestName) .Select(i => i.EventArgs) .ToEvent().OnNext += (args) => { if (args.Response.Errors != null && args.Response.Errors.Any()) { completionSource.TrySetException(args.Response.Errors.Select(j => new Exception(j.ErrorMessage))); } else { completionSource.TrySetResult(args); } }; return completionSource.Task; }
解决方法
RunAsync和ToTask都生成observable中的最后一个值.因此,在观察完成之前不会产生任何价值.但是使用FromEventPattern创建的可观察量通常不会完成.你需要强迫他们完成Take或Until之类的东西.
我还要注意RunAsync和ToTask本质上是多余的,不需要两者兼顾.
在你的情况下,我假设你真的对通过你的过滤器的第一个值感兴趣:
var task = Observable .FromEventPattern<MessageResponseEventArgs>(communicator,"PushMessageRecieved") .FirstAsync(i => i.EventArgs.GetRequestFromReceivedMessage().Name == requestName) .Select(i => i.EventArgs) .ToTask(); task.Wait();