如何在c#中触发事件之前阻塞

Arl*_*ler 54 c# events

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

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

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

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

接受答案这个问题我问的是我做什么,但它只是感觉并不完全正确.几乎感觉ManuelResetEvent触发和检索数据并返回它的程序之间的数据可能会发生.

更新:主要问题Auto/ManualResetEvent是它太脆弱了.线程可以等待事件,然后在将其更改为其他内容之前,没有足够的时间让其他人获取它.有没有办法使用锁或其他东西?也许使用get和set语句.

Vin*_*oth 40

您可以使用ManualResetEvent.在触发辅助线程之前重置事件,然后使用WaitOne()方法阻止当前线程.然后,您可以让辅助线程设置ManualResetEvent,这将导致主线程继续.像这样的东西:

ManualResetEvent oSignalEvent = new ManualResetEvent(false);

void SecondThread(){
    //DoStuff
    oSignalEvent.Set();
}

void Main(){
    //DoStuff
    //Call second thread
    System.Threading.Thread oSecondThread = new System.Threading.Thread(SecondThread);
    oSecondThread.Start();

    oSignalEvent.WaitOne(); //This thread will block here until the reset event is sent.
    oSignalEvent.Reset();
    //Do more stuff
}
Run Code Online (Sandbox Code Playgroud)


Ada*_*dam 34

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

    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);
    }
Run Code Online (Sandbox Code Playgroud)

此示例使用具有名为WelcomeTitle的文本块和两个按钮的表单.单击第一个按钮时,它会启动单击事件,但会在等待行停止.单击第二个按钮时,任务完成并更新WelcomeTitle文本.如果你想要超时,那么改变

await tcs.Task;
Run Code Online (Sandbox Code Playgroud)

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

  • 您不需要异步来使用 TaskCompletionSource (2认同)
  • 这是真的,但如果您想在不阻塞 UI 的情况下等待任务,则确实需要它。 (2认同)