【发布时间】:2014-06-08 21:58:44
【问题描述】:
为什么task 永远等待?:
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;
}
【问题讨论】:
-
Name属性是否匹配requestName? -
@Lee:如果它达到了
Selectlambda,正如 OP 所说,那么是的,它必须匹配 Where 子句。 -
ToTask 不应该在 RunAsync 之前发生吗?
-
@travis-j
RunAsync返回AsyncSubject<TSource> -
FWIW @JamesWorld 提出了很好的观点。
ToTask仅适用于将新的 Rx 代码与现有的基于任务的代码集成的目的。如果您不尝试将新的 Rx 事件与现有的任务代码集成,最好不要调用ToTask。您仍然可以使用 Rx(等待、等待、延续)更好地完成所有类似任务的事情。
标签: c# task-parallel-library system.reactive