gpt4 book ai didi

c# - "async void"WPF 命令处理程序中的异常处理

转载 作者:可可西里 更新时间:2023-11-01 09:07:22 29 4
gpt4 key购买 nike

我正在审查我同事的一些 WPF 代码,这是一个UserControl-based components with a lot of async void 事件和命令处理程序。这些方法目前没有在内部实现任何错误处理

代码简述:

<Window.CommandBindings>
<CommandBinding
Command="ApplicationCommands.New"
Executed="NewCommand_Executed"/>
</Window.CommandBindings>
private async void NewCommand_Executed(object sender, ExecutedRoutedEventArgs e)
{
// do some fake async work (and may throw if timeout < -1)
var timeout = new Random(Environment.TickCount).Next(-100, 100);
await Task.Delay(timeout);
}

NewCommand_Executed 中抛出但未观察到的异常 只能在全局级别处理(例如,使用 AppDomain.CurrentDomain.UnhandledException)。显然,这不是一个好主意。

我可以在本地处理异常:

private async void NewCommand_Executed(object sender, ExecutedRoutedEventArgs e)
{
try
{
// do some fake async work (throws if timeout < -1)
var timeout = new Random(Environment.TickCount).Next(-100, 100);
await Task.Delay(timeout);
}
catch (Exception ex)
{
// somehow log and report the error
MessageBox.Show(ex.Message);
}
}

但是,在这种情况下,宿主应用程序的 ViewModel 不会意识到 NewCommand_Executed 中的错误。这也不是理想的解决方案,而且错误报告 UI 不应始终是库代码的一部分。

另一种方法是在本地处理它们并触发专用错误事件:

public class AsyncErrorEventArgs: EventArgs
{
public object Sender { get; internal set; }
public ExecutedRoutedEventArgs Args { get; internal set; }
public ExceptionDispatchInfo ExceptionInfo { get; internal set; }
}

public delegate void AsyncErrorEventHandler(object sender, AsyncErrorEventArgs e);

public event AsyncErrorEventHandler AsyncErrorEvent;

private async void NewCommand_Executed(object sender, ExecutedRoutedEventArgs e)
{
ExceptionDispatchInfo exceptionInfo = null;

try
{
// do some fake async work (throws if timeout < -1)
var timeout = new Random(Environment.TickCount).Next(-100, 100);
await Task.Delay(timeout);
}
catch (Exception ex)
{
// capture the error
exceptionInfo = ExceptionDispatchInfo.Capture(ex);
}

if (exceptionInfo != null && this.AsyncErrorEvent != null)
this.AsyncErrorEvent(sender, new AsyncErrorEventArgs {
Sender = this, Args = e, ExceptionInfo = exceptionInfo });
}

我最喜欢最后一个,但如果有任何其他建议,我将不胜感激,因为我在 WPF 方面的经验有限。

  • 是否已建立 WPF 模式来将错误从 async void 命令处理程序传播到 ViewModal?

  • 在 WPF 命令处理程序中执行异步工作通常不是一个好主意吗,因为它们可能用于快速同步 UI 更新?

我是在 WPF 的上下文中问这个问题,但我认为它也适用于 WinForms 中的 async void 事件处理程序。

最佳答案

这里的问题是您的 UserControl 库不是以典型的 MVVM 方式构建的。通常,对于重要的命令,您的 UserControl 的代码不会直接绑定(bind)到命令,而是具有在设置时(通过绑定(bind)到 ViewModel)会触发控件中的操作的属性。然后您的 ViewModel 将绑定(bind)到应用程序命令,并设置适当的属性。 (或者,您的 MVVM 框架可能有另一个消息传递方案,可用于 ViewModel 和 View 之间的交互)。

至于UI内部抛出的Exception,我又觉得是架构问题。如果 UserControl 不仅仅充当 View (即运行任何类型的可能导致意外异常的业务逻辑),则应将其分为 View 和 View 模型。 ViewModel 将运行逻辑,并且可以由您的其他应用程序 ViewModel 实例化,或者通过另一种方法进行通信(如上所述)。

如果 UserControl 的布局/可视化代码抛出异常,那么您的 ViewModel 应该(几乎没有异常(exception))以任何方式捕获异常。正如您所提到的,这应该只由全局级别的处理程序处理日志记录。

最后,如果控件代码中确实存在需要通知您的 ViewModel 的已知“异常”,我建议捕获已知异常并引发事件/命令并设置属性。但同样,这真的不应该用于异常,只是预期的“错误”状态。

关于c# - "async void"WPF 命令处理程序中的异常处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21231739/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com