加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – IObservable.ToTask方法返回等待激活的Task

发布时间:2020-12-15 18:26:39 所属栏目:百科 来源:网络整理
导读:为什么任务永远等待?: var task = Observable .FromEventPatternMessageResponseEventArgs(communicator,"PushMessageRecieved") .Where(i = i.EventArgs.GetRequestFromReceivedMessage().Name == requestName) .Select(i = i.EventArgs) .RunAsync(Syste
为什么任务永远等待?:
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();

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读