是否可以等待事件而不是另一种异步方法? [英] Is it possible to await an event instead of another async method?

查看:22
本文介绍了是否可以等待事件而不是另一种异步方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的 C#/XAML Metro 应用程序中,有一个按钮可以启动一个长期运行的进程.因此,按照建议,我使用 async/await 来确保 UI 线程不会被阻塞:

In my C#/XAML metro app, there's a button which kicks off a long-running process. So, as recommended, I'm using async/await to make sure the UI thread doesn't get blocked:

private async void Button_Click_1(object sender, RoutedEventArgs e) 
{
     await GetResults();
}

private async Task GetResults()
{ 
     // Do lot of complex stuff that takes a long time
     // (e.g. contact some web services)
  ...
}

有时,GetResults 中发生的事情需要额外的用户输入才能继续.为简单起见,假设用户只需点击继续"按钮即可.

Occasionally, the stuff happening within GetResults would require additional user input before it can continue. For simplicity, let's say the user just has to click a "continue" button.

我的问题是:如何以等待 事件(例如单击另一个按钮)的方式暂停 GetResults 的执行?

My question is: how can I suspend the execution of GetResults in such a way that it awaits an event such as the click of another button?

这是一种实现我正在寻找的丑陋方法:继续"按钮的事件处理程序设置一个标志...

Here's an ugly way to achieve what I'm looking for: the event handler for the continue" button sets a flag...

private bool _continue = false;
private void buttonContinue_Click(object sender, RoutedEventArgs e)
{
    _continue = true;
}

... 并且 GetResults 会定期对其进行轮询:

... and GetResults periodically polls it:

 buttonContinue.Visibility = Visibility.Visible;
 while (!_continue) await Task.Delay(100);  // poll _continue every 100ms
 buttonContinue.Visibility = Visibility.Collapsed;

投票显然很糟糕(忙于等待/浪费周期),我正在寻找基于事件的东西.

The polling is clearly terrible (busy waiting / waste of cycles) and I'm looking for something event-based.

有什么想法吗?

顺便说一下,在这个简化的例子中,一个解决方案当然是将 GetResults() 分成两部分,从开始按钮调用第一部分,从继续按钮调用第二部分.实际上,GetResults 中发生的事情更为复杂,在执行过程中的不同点可能需要不同类型的用户输入.因此,将逻辑分解为多个方法并非易事.

Btw in this simplified example, one solution would be of course to split up GetResults() into two parts, invoke the first part from the start button and the second part from the continue button. In reality, the stuff happening in GetResults is more complex and different types of user input can be required at different points within the execution. So breaking up the logic into multiple methods would be non-trivial.

推荐答案

您可以使用 SemaphoreSlim Class 作为信号:

You can use an instance of the SemaphoreSlim Class as a signal:

private SemaphoreSlim signal = new SemaphoreSlim(0, 1);

// set signal in event
signal.Release();

// wait for signal somewhere else
await signal.WaitAsync();

<小时>

或者,您可以使用 TaskCompletionSource 的实例.类创建一个任务,代表按钮点击的结果:


Alternatively, you can use an instance of the TaskCompletionSource<T> Class to create a Task<T> that represents the result of the button click:

private TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>();

// complete task in event
tcs.SetResult(true);

// wait for task somewhere else
await tcs.Task;

这篇关于是否可以等待事件而不是另一种异步方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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