【问题标题】:How to convert EventHandler<MyMessage> parameter into async/await?如何将 EventHandler<MyMessage> 参数转换为 async/await?
【发布时间】:2022-01-28 22:36:37
【问题描述】:

我必须使用以下 API(基本上我必须订阅 Stan 中的主题/频道/主题):

IStanSubscription Subscribe(string subject, StanSubscriptionOptions options, EventHandler<StanMsgHandlerArgs> handler);

我想将 EAP 模式转换为 TAP 模式。我所做的如下:

public Task<MyMessage> Subscribe(string subject)
{
    var tcs = new TaskCompletionSource<MyMessage>();

    _stanConnection.Subscribe(subject, GetStanSubscriptionOptions(), (sender, args) =>
    {
        string messageAsString = Encoding.UTF8.GetString(args.Message.Data, 0, args.Message.Data.Length);

        try
        {
            args.Message.Ack();

            MyMessage message = JsonConvert.DeserializeObject<MyMessage>(messageAsString);

            tcs.SetResult(message);

        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);
        }
    });

    return tcs.Task;
}

第一条消息一切正常,但下一条消息抛出以下异常:

An attempt was made to transition a task to a final state when it had already completed

我阅读了一些文章和主题,例如:

据我所知(我对 EventHandler 的高级应用不太了解)在这两种情况下,它们都直接从类中访问 EventHandler,而在我的情况下,EventHandler 作为参数传递,我不确定如何取消订阅。

干杯!

【问题讨论】:

  • TaskCompletionSource 只能设置一次。顺便说一句,你应该在 catch 块内调用SetException

标签: c# asynchronous task-parallel-library nats.io event-based-programming


【解决方案1】:

我想将 EAP 模式转换为 TAP 模式。

如果 API 是使用 EAP 模式编写的,那就可以了。但事实并非如此。相反,它使用自己的订阅模式,使用委托来触发更新。

所以,你的选择是:

  1. 将自定义订阅模式映射到标准Observable pattern
  2. 构建一个缓冲区(例如,System.Threading.Channels),让事件处理程序将项目添加到缓冲区,然后将它们作为异步流使用。

使用这两个选项,请务必同时处理“取消订阅”逻辑。

【讨论】:

    猜你喜欢
    • 2021-10-19
    • 2021-04-10
    • 2014-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-10
    • 2019-08-11
    • 2019-11-08
    相关资源
    最近更新 更多