如何“等待”提高EventHandler事件 [英] How to 'await' raising an EventHandler event

查看:265
本文介绍了如何“等待”提高EventHandler事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有时,事件模式用于通过子视图模型在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 SynchronizationContexts 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屋!

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