async/await Model View Presenter winforms
本文关键字:Presenter winforms View Model await async | 更新日期: 2023-09-27 17:53:41
我有一个winforms应用程序,它使用了这篇文章中描述的MVP模式http://www.codeproject.com/Articles/563809/UIplusDesignplusUsingplusModel-View-Presenter我正在将我的应用程序转换为async/await,但我有问题。
这里有一个例子来说明我的问题
public interface IView
{
event Action DoSomething;
}
public partial class MyForm : Form, IView
{
public event Action DoSomething;
public MyForm()
{
InitializeComponent();
}
private async void OnSomeButtonClick(object sender, EventArgs e)
{
if (DoSomething!= null)
{
try
{
await DoSomething();
SomeOtherMethod();
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
}
public class MyPresenter
{
private readonly IView _view;
private ClassWithAwaitbleMethods _foo;
public MyPresenter(IView view)
{
_view = view;
_view.DoSomething += OnDoSomething;
_foo = new ClassWithAwaitableMethods();
}
public async void OnDoSomething()
{
//this may throw an exception
await _foo.SomeAwaitableWork1();
}
}
public class MySecondPresenter
{
private readonly IView _view;
private ClassWithAwaitbleMethods _foo;
public MySecondPresenter(IView view)
{
_view = view;
_view.DoSomething += OnDoSomething;
_foo = new AnotherClassWithAwaitableMethods();
}
public async void OnDoSomething()
{
//this may throw an exception
await _foo.SomeAwaitableWork2();
}
}
这段代码没有正确地等待,当抛出异常时,它没有被捕获。这是因为async void。当这段代码不是async/await时,异常被很好地捕获。
我知道async void是一个禁忌,除了顶级事件,但我的应用程序的设计方式,我不能真的绕过它。当我只有一个订阅者时,我将IView接口更改为
public interface IView
{
Func<Task> DoSomething {get; set;};
}
然后像这样连接起来
public MyPresenter(IView view)
{
_view = view;
_view.DoSomething = OnDoSomething;
_foo = new ClassWithAwaitableMethods();
}
虽然有点粗糙,但是可以正确地等待并捕获异常。如有任何帮助或见解,我将不胜感激。
核心问题是代码使用事件作为策略模式而不是观察者模式。按照目前的情况,你对这段代码做不了什么;正确的重构需要回调接口而不是事件。例如:
// An instance of this is passed into the concrete view.
public interface IViewImplementation
{
void DoSomething();
// Or the async equivalent:
// Task DoSomethingAsync();
}
但是,如果这种级别的重构令人讨厌,您可以应用一些变通方法。我在我的博客上报道了这类"异步事件"。有几种方法;定义一个返回Task
的事件是可能的(尽管有些尴尬)。不过,我最喜欢的方法是延迟,主要是因为延迟是WinRT开发人员已经熟悉的概念。