在对话框视图模型的异步加载中捕获异常

时间:2014-10-30 14:50:00

标签: c# wpf mvvm dialog async-await

我有DialogViewModelasync Task LoadData()方法。此方法异步加载数据并显示此对话框,通知用户有关加载的信息。这是代码:

try
{
    var dialog = new DialogViewModel();
    var loadTask = dialog.LoadData();
    WindowManager.ShowDialog(dialog);
    await loadTask;
}
catch (Exception ex)
{
    Logger.Error("Error in DialogViewModel", ex);
    // Notify user about the error
}

LoadData抛出异常时,在用户退出对话框之前不会处理它。这是因为在调用await时处理了异常,并且在WindowManager.ShowDialog(dialog)完成之前不会发生异常。

显示异步加载对话框的正确方法是什么?我试过这种方式:

  1. LoadData(),构造函数或类似内容中调用OnShow()。但如果我需要在没有任何数据的情况下显示此对话框,这将无法工作
  2. 在显示对话框之前调用await LoadData()。这样用户必须在实际看到窗口之前等待数据加载,但我希望窗口能够立即显示加载指示器。

1 个答案:

答案 0 :(得分:0)

为什么有明确的公开LoadData方法?

如果必须这样做,那么使用带有Task<T>的{​​{1}}异步地在构造函数内部执行它,以通过检查返回任务上的ContinueWith属性来处理生成的任何异常。

这将解决您已突出显示的两个问题。

下面显示了一个非常简单的示例,显然您的实施将更加复杂。

IsFaulted

或者,如果您不想明确使用public class DialogViewModel { private Task _task; public DialogViewModel() { var context = TaskScheduler.FromCurrentSynchronizationContext(); _task = Task.Factory.StartNew(() => { var data = GetDataCollection(); return data; }) .ContinueWith(t => { if (t.IsFaulted) { HasErrored = true; ErrorMessage = "It's borked!"; } else { Data = t.Result; } }, context); } public IEnumerable<string> Data { get; private set; } public bool HasErrored { get; private set; } public string ErrorMessage { get; private set; } private static IEnumerable<string> GetDataCollection() { return new List<string>() { "John", "Jack", "Steve" }; } } 并希望使用async \ await功能,则可以使用稍微不同的方法,因为您不能将async \ await与类构造函数一起使用:

Task<T>