这是一种在事件中使用Async的安全方法

时间:2015-09-11 12:07:45

标签: winforms async-await

我以前使用任务并行库来保持UI线程响应,但我正在尝试切换到async / await来简化代码。我正在研究的项目是WinForms。有一个与视图接口通信的表示层,以及一个包含实现这些接口的winforms表单的程序集,依赖注入将所有内容绑定在一起。在下面的具体示例中,表单具有菜单/按钮/等,其向表示层发送用于新数据的请求。我忽略了异常处理以保持示例简单。

在表单代码中,我们有一个这样的事件处理程序:

private async sub DataRequest(sender as object, e as EventArgs) handles SomeButton.click
        Dim etask = New Threading.Tasks.Task(Sub() RaiseEvent DataRefreshRequest(Me, EventArgs.Empty))
        etask.Start()
        Await etask
end sub

不确定是否有更简洁的等待事件被提出的方式,上面看起来有点笨拙

表示层使用以下代码响应此事件:

Private Async Sub HandleDataRequest() Handles _view.DataRefreshRequest
  Dim gdtask = New Tasks.Task(Of IEnumerable(Of Summary))(Function() GetDataTask())
  gdtask.Start()
  _view.Data = Await gdtask
End Sub

我们在这个项目上遇到了.Net 4,所以我们使用的是Microsoft.BCL.Async。 GetDataTask实际上是对业务层公开的实体的Linq查询,但没有.Net 4.5,我们无法使用.ToListAsync执行它

我有点不确定的是我在winforms组装中提升事件的方式。这是正确的方法吗?它似乎工作正常,但我担心这样做的任何无法预料的问题。最好从一开始就做到这一点,一旦这种模式被普遍使用,就会发现存在问题。

1 个答案:

答案 0 :(得分:2)

使用public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } ); } 优于使用Task.Run的{​​{1}}构造函数。

除此之外,我只是建议一些评论。正如您所指出的,理想的解决方案是使用Task并使其真正异步,但鉴于您的平台,这是不可能的。

Task.Start 通常用于在后台线程上运行CPU绑定代码,此代码不受CPU限制。因此,我建议您对自己的未来发表评论,以便在升级到.NET 4.5时,您可以知道不再需要这些ToListAsync次呼叫。