一尘不染

是否可以等待事件而不是其他异步方法?

c#

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

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中发生的事情可能需要其他用户输入才能继续。为了简单起见,假设用户只需单击“继续”按钮。

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

这是实现我要查找的内容的一种丑陋方式:“继续”的事件处理程序”按钮设置了一个标志…

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

…,并且GetResults定期轮询它:

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

轮询显然很糟糕(繁忙的等待/浪费时间),我正在寻找基于事件的东西。

有任何想法吗?

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


阅读 244

收藏
2020-05-19

共1个答案

一尘不染

您可以将SemaphoreSlim类的实例用作信号:

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

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

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

或者,您可以使用TaskCompletionSource 的实例来创建代表按钮单击结果的Task

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

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

// wait for task somewhere else
await tcs.Task;
2020-05-19