如何等待事件处理程序调用? [英] how to await an event handler invocation?

查看:263
本文介绍了如何等待事件处理程序调用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

基本上,我有一个调用事件处理程序的方法.事件处理程序调用了一个异步方法,我需要知道该方法的结果(对或错).由于事件处理程序只能返回void,因此我创建了一个自己的eventargs,其成功属性在正确的情况下在该方法中设置为true.

basically, i have a method which invokes an event handler. the event handler calls an async method and i need to know the results of that method (true or false). since event handlers can only return void, I created my own eventargs with a success property which i set to true in that method if it goes right.

public virtual async Task<bool> TrySomething()
        {
            var args = new MyEventArgs();
            SomeEvent?.Invoke(this, args);
            return args.Success;
        }

SomeEvent已连接到SomeEventHandler

SomeEvent is hooked up to SomeEventHandler

private async void SomeEventHandler(object sender, MyEventArgs e)
        {
            e.Success = await AnAsyncMethod();
        }

private asyc Task<bool> AnAsyncMethod()
{
  //...
}

令我感到困惑的是,是否可以保证TrySomething方法将等待SomeEvent完成,以便成功设置成功,然后返回它?如果没有,我如何确保它能做到?

What im confused by is that, is there any guarantee that the method TrySomething will wait for the SomeEvent to finish so Success has been set, before returning it? And if not, how can I ensure that it does?

谢谢

推荐答案

是否可以保证TrySomething方法将等待SomeEvent完成,以便在返回成功之前已设置成功?

is there any guarantee that the method TrySomething will wait for the SomeEvent to finish so Success has been set, before returning it?

不. async void的意思是完成后不通知呼叫者".因此,引发事件的代码无法知道事件处理程序何时完成,除非您自己编写该附加逻辑.

No. async void means "don't notify the caller when I finish". So the code raising your event cannot know when the event handler has completed, unless you write that additional logic yourself.

如果没有,我如何确保它呢?

And if not, how can I ensure that it does?

嗯,这是一个棘手的问题. .NET事件被设计为我称之为通知事件"-也就是说,当事件触发时,它会通知其所有侦听器.不需要等待",因为侦听器无法向通知者提供反馈.

Well, that's more of a tricky question. .NET events are designed as what I call "notification events" - that is, when an event fires, it notifies all its listeners. There's no need for "waiting" because there's no way for a listener to provide feedback to the notifier.

您的代码是我称之为命令事件"-是event但与通知事件的语义不匹配的代码.您的代码需要处理程序的响应.

Your code is an example of what I call a "command event" - code that is an event but doesn't match the semantics of a notification event. Your code wants a response from the handler.

因此,您需要问自己的第一个问题是我真的希望这成为一个活动吗?"对此的一个很好的检验是:如果有多个处理程序,我可以定义有意义的语义吗?"

So, the first question you need to ask yourself is "do I really want this to be an event?" One good litmus test for this is "can I define meaningful semantics if there are multiple handlers?"

更具体地说,如果将多个处理程序挂接到事件上,您的代码应如何表现?也许答案是那没有道理".或答案可能是我要等所有全部完成,并且只有全部成功"才是成功"".或如果所有人任何为'成功',则等待所有人并'成功'".或等待第一个完成并使用该结果".或等待他们一次完成,直到第一次成功就停止".或等待他们一次完成一个任务,在第一次失败时停止".这些是立即想到的选择.可能还会更多.

More specifically, how should your code behave if multiple handlers are hooked up to the event? Perhaps the answer is "that wouldn't make sense". Or perhaps the answer is "I want to wait for all of them to complete and only be 'successful' if all of them are 'successful'". Or "wait for all and be 'successful' if any of them are 'successful'". Or "wait for the first one to complete and use that result". Or "wait for them to complete one at a time, stopping on the first success". Or "wait for them to complete one at a time, stopping on the first failure". These are the choices that come immediately to mind; there could be more.

如果答案是这不会在我的代码中发生"或不止一个处理程序没有道理"或现在很难做出决定",那么适当的答案是删除event .这不是一个事件.这是一个方法调用.在设计模式术语中, events用于实现观察者模式,但是您拥有的是策略模式 ,这就是event身体不好.在这种情况下,您可以使用 Gabriel的答案或类似的方法,您可以使用界面来定义策略,而不必提出事件,您将在该接口上调用方法.

If the answer is "that's not going to happen in my code" or "more than one handler doesn't make sense" or "that's too hard of a decision to make right now", then the appropriate answer is to remove the event. It's not an event. It's a method call. In Design Pattern terminology, events are used to implement the Observer Pattern, but what you have is a Strategy Pattern, and that's why events are a poor fit. In this case, you could use Gabriel's answer or something similar where you define the Strategy using an interface, and instead of raising an event you would invoke a method on that interface.

但是,如果确实具有多个处理程序,并且可以使用 有意义的语义,那么您需要修改EventArgs键入具有某种收集器"的响应,然后让您的事件引发代码解释这些响应.确切的代码会根据您所需的语义而有所不同.

However, if it does make sense to have multiple handlers, and there is a meaningful semantic you can use, then you'll need to modify the EventArgs type to have some sort of "collector" of responses, and then have your event-raising code interpret those responses. The exact code would vary based on the semantics you need.

这篇关于如何等待事件处理程序调用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆