如何“等待”提高EventHandler事件 [英] How to 'await' raising an EventHandler event
问题描述
有时,事件模式用于通过子视图模型在MVVM应用程序中引发事件,以松散耦合的方式向其父视图模型发送消息。
Sometimes the event pattern is used to raise events in MVVM applications by or a child viewmodel to send a message to its parent viewmodel in a loosely coupled way like this.
父ViewModel
searchWidgetViewModel.SearchRequest += (s,e) =>
{
SearchOrders(searchWidgitViewModel.SearchCriteria);
};
SearchWidget ViewModel
public event EventHandler SearchRequest;
SearchCommand = new RelayCommand(() => {
IsSearching = true;
if (SearchRequest != null)
{
SearchRequest(this, EventArgs.Empty);
}
IsSearching = false;
});
在重构我的.NET4.5应用程序我正在尽可能多地使用代码,使用 async
和等待
。但是以下内容不行(我真的不期待)
In refactoring my application for .NET4.5 I am making as much as code possible to use async
and await
. However the following doesn't work (well I really wasn't expecting it to)
await SearchRequest(this, EventArgs.Empty);
框架肯定会这样来调用事件处理程序如此,但我不知道该怎么做?
The framework definitely does this to call event handlers such as this, but I'm not sure how it does it?
private async void button1_Click(object sender, RoutedEventArgs e)
{
textBlock1.Text = "Click Started";
await DoWork();
textBlock2.Text = "Click Finished";
}
我发现有关提升事件异常的事情是 古代,但我在框架中找不到支持的东西。
Anything I've found on the subject of raising events asynchrously is ancient but I can't find something in the framework to support this.
我如何等待
调用事件,但仍保留在UI线程上。
How can I await
the calling of an event but remain on the UI thread.
推荐答案
UI处理 async
事件的方式与您要做的不同。 UI 提供了一个 SynchronizationContext
其异步
事件,使他们能够在UI线程上恢复。
The way UIs handle async
events is different than what you're trying to do. The UI provides a SynchronizationContext
to its async
events, enabling them to resume on the UI thread. It does not ever "await" them.
最佳解决方案(IMO)
我认为最好的选择是使用 async -friendly pub / sub系统.msdn.com / b / pfxteam / archive / 2012/02/11 / 10266930.aspxrel =noreferrer> AsyncCountdownEvent
知道所有处理程序已经完成了。
I think the best option is to build your own async
-friendly pub/sub system, using AsyncCountdownEvent
to know when all handlers have completed.
较小的解决方案#1
async void
方法在开始和结束(通过递增/递减异步操作的计数)时通知他们的 SynchronizationContext
。所有UI SynchronizationContext
忽略这些通知,但您可以构建一个跟踪它的包装器,并在计数为零时返回。
async void
methods do notify their SynchronizationContext
when they start and finish (by incrementing/decrementing the count of asynchronous operations). All UI SynchronizationContext
s ignore these notifications, but you could build a wrapper that tracks it and returns when the count is zero.
这是一个例子,使用 AsyncContext
从我的 AsyncEx库:
Here's an example, using AsyncContext
from my AsyncEx library:
SearchCommand = new RelayCommand(() => {
IsSearching = true;
if (SearchRequest != null)
{
AsyncContext.Run(() => SearchRequest(this, EventArgs.Empty));
}
IsSearching = false;
});
然而,在这个例子中,UI线程是不是在运行
。
However, in this example the UI thread is not pumping messages while it's in Run
.
较小的解决方案#2
您还可以根据嵌套的 Dispatcher
框架自己创建 SynchronizationContext
异步操作的计数达到零。然而,您会引入重新入侵问题; DoEvents
被遗漏在WPF中。
You could also make your own SynchronizationContext
based on a nested Dispatcher
frame that pops itself when the count of asynchronous operations reaches zero. However, you then introduce re-entrancy problems; DoEvents
was left out of WPF on purpose.
这篇关于如何“等待”提高EventHandler事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!