如何在c#中阻塞直到触发事件 [英] How to block until an event is fired in c#

查看:30
本文介绍了如何在c#中阻塞直到触发事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在询问这个问题之后,我想知道是否可以等待一个事件被触发,然后获取事件数据并返回其中的一部分.有点像这样:

After asking this question, I am wondering if it is possible to wait for an event to be fired, and then get the event data and return part of it. Sort of like this:

private event MyEventHandler event;
public string ReadLine(){ return event.waitForValue().Message; }
...
event("My String");
...elsewhere...
var resp = ReadLine();

请确保您提供的任何解决方案直接返回值,而不是从其他地方获取.我在问上面的方法是否以某种方式可用.我知道 Auto/ManuelResetEvent,但我不知道它们像我上面那样直接返回值.

Please make sure whatever solution you provide returns the value directly rather than getting it from something else. I'm asking if the method above is available in some way. I know about Auto/ManuelResetEvent, but I don't know that they return the value directly like I did above.

更新: 我使用 MyEventHandler(其中包含一个 Message 字段)声明了一个事件.我在另一个名为 ReadLine 的线程中有一个方法等待事件触发.当事件触发 WaitForValue 方法(事件处理场景的一部分)时,返回包含消息的事件参数.然后该消息由 ReadLine 返回给调用它的任何对象.

Update: I declared an event using MyEventHandler (which contains a Message field). I have a method in another thread called ReadLine waiting for the event to fire. When the event fires the WaitForValue method (part of the event handling scene) returns the event args, which contains the message. The message is then returned by ReadLine to whatever had called it.

接受的答案那个问题我问的是我做了什么,但感觉不太对.几乎感觉在 ManuelResetEvent 触发和程序检索数据并返回数据之间的数据可能发生了什么.

The accepted answer to that question I asked was what I did, but it just doesn't feel quite right. It almost feels like something could happen to the data between the ManuelResetEvent firing and the program retrieving the data and returning it.

更新:Auto/ManualResetEvent 的主要问题是它太容易受到攻击.线程可能会等待该事件,然后在将其更改为其他内容之前不会给其他任何人足够的时间来获取它.有没有办法使用锁或其他东西?也许使用 get 和 set 语句.

Update: The main problem with the Auto/ManualResetEvent is that it is too vulnerable. A thread could wait for the event, and then not give enough time for anyone else to get it before changing it to something else. Is there a way to use locks or something else? Maybe using get and set statements.

推荐答案

如果当前方法是异步的,那么您可以使用 TaskCompletionSource.创建一个事件处理程序和当前方法可以访问的字段.

If the current method is async then you can use TaskCompletionSource. Create a field that the event handler and the current method can access.

    TaskCompletionSource<bool> tcs = null;

    private async void Button_Click(object sender, RoutedEventArgs e)
    {
        tcs = new TaskCompletionSource<bool>();
        await tcs.Task;
        WelcomeTitle.Text = "Finished work";
    }

    private void Button_Click2(object sender, RoutedEventArgs e)
    {
        tcs?.TrySetResult(true);
    }

这个例子使用了一个表单,它有一个名为 WelcomeTitle 的文本块和两个按钮.单击第一个按钮时,它会启动单击事件,但会在等待行停止.单击第二个按钮时,任务完成并更新 WelcomeTitle 文本.如果您也想超时,请更改

This example uses a form that has a textblock named WelcomeTitle and two buttons. When the first button is clicked it starts the click event but stops at the await line. When the second button is clicked the task is completed and the WelcomeTitle text is updated. If you want to timeout as well then change

await tcs.Task;

await Task.WhenAny(tcs.Task, Task.Delay(25000));
if (tcs.Task.IsCompleted)
    WelcomeTitle.Text = "Task Completed";
else
    WelcomeTitle.Text = "Task Timed Out";

这篇关于如何在c#中阻塞直到触发事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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