3 回答
TA贡献1752条经验 获得超4个赞
如果你有一件不寻常的事情await
,那么最简单的答案往往是TaskCompletionSource
(或者是一些async
基于原始的原语TaskCompletionSource
)。
在这种情况下,您的需求非常简单,因此您可以直接使用TaskCompletionSource
:
private TaskCompletionSource<object> continueClicked;private async void Button_Click_1(object sender, RoutedEventArgs e) { // Note: You probably want to disable this button while "in progress" so the // user can't click it twice. await GetResults(); // And re-enable the button here, possibly in a finally block.}private async Task GetResults(){ // Do lot of complex stuff that takes a long time // (e.g. contact some web services) // Wait for the user to click Continue. continueClicked = new TaskCompletionSource<object>(); buttonContinue.Visibility = Visibility.Visible; await continueClicked.Task; buttonContinue.Visibility = Visibility.Collapsed; // More work...}private void buttonContinue_Click(object sender, RoutedEventArgs e){ if (continueClicked != null) continueClicked.TrySetResult(null);}
逻辑上,TaskCompletionSource
就像一个async
ManualResetEvent
,除了你只能“设置”事件一次,事件可以有一个“结果”(在这种情况下,我们没有使用它,所以我们只是设置结果null
)。
TA贡献1802条经验 获得超4个赞
这是我使用的实用程序类:
public class AsyncEventListener
{
private readonly Func<bool> _predicate;
public AsyncEventListener() : this(() => true)
{
}
public AsyncEventListener(Func<bool> predicate)
{
_predicate = predicate;
Successfully = new Task(() => { });
}
public void Listen(object sender, EventArgs eventArgs)
{
if (!Successfully.IsCompleted && _predicate.Invoke())
{
Successfully.RunSynchronously();
}
}
public Task Successfully { get; }
}
以下是我如何使用它:
var itChanged = new AsyncEventListener();
someObject.PropertyChanged += itChanged.Listen;
// ... make it change ...
await itChanged.Successfully;
someObject.PropertyChanged -= itChanged.Listen;
- 3 回答
- 0 关注
- 463 浏览
添加回答
举报