c# - 异步数据加载及后续错误处理

标签 c# .net asynchronous error-handling async-await

我有一个涉及数据库的应用程序。以前,在打开窗口时,我会查询数据库并使用它来填充 View 模型的各个方面。这工作得相当好,但当数据访问时间比预期长时可能会造成明显的暂停。

当然,自然的解决方案是异步运行数据库查询,然后在查询完成时填充 View 模型。这并不太难,但它提出了一些有关错误处理的有趣问题。

以前,如果数据库查询出现问题(这是一个相当大的问题,当然),我会通过 View 模型构造函数传播异常,最终将其返回给想要打开窗口的调用者。然后它可能会显示适当的错误,但实际上不会打开窗口。

但是现在,窗口会立即打开,然后在查询完成后填充。现在的问题是,我应该在什么时候检查后台任务中的错误?窗口已经打开,因此行为需要以某种方式有所不同,但是向用户指示失败并允许正常恢复/关闭的干净方法是什么?

作为引用,这里是演示基本模式的片段:

    public ViewModel()
    {
        _initTask = InitAsync();
        //Now where do I check on the status of the init task?
    }

    private async Task InitAsync()
    {
        //Do stuff...
    }

    //....

    public void ShowWindow()
    {
        var vm = new ViewModel(); //Previously this could throw an exception that would prevent window from being shown
        _windowServices.Show(vm);
    }

我考虑过的一个选项是使用异步工厂方法来构造 ViewModel,允许在尝试显示窗口之前构造和初始化整个事物。这保留了在窗口打开之前报告错误的旧方法。然而,它放弃了通过这种方法获得的一些 UI 响应能力,这允许窗口的初始加载与查询并行发生,并且还允许我(在某些情况下)在每个查询完成时增量更新 UI,而不是而不是让 UI 立即自行组合。它避免了锁定 UI 线程,但并没有减少用户实际看到窗口并开始与其交互之前的时间。

最佳答案

也许在你的 View 模型和底层服务之间使用某种消息传递/中介?

使用MVVMLight的半伪代码

public ViewModel()
{
    Messenger.Default.Register<NotificationMessage<Exception>>(this, message =>
        {
            // Handle here
        });

    Task.Factory.StartNew(() => FetchData());
}

public async Task FetchData()
{
    // Some magic happens here
    try
    {
        Thread.Sleep(2000);
        throw new ArgumentException();
    }
    catch (Exception e)
    {
        Messenger.Default.Send(new NotificationMessage<Exception>(this, e, "Aw snap!"));
    }
}

关于c# - 异步数据加载及后续错误处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22052507/

相关文章:

node.js - 在 Node 的 async 模块中使用函数的参数

c# - Task.Run 和 UI 进度更新

javascript - Console.log 异步 Facebook Like 按钮加载(显示)后的内容

c# - Unity3D C# 中的相机旋转问题(可能很容易修复)

c# - 确保文本框的第一个和最后一个字符是数字c#

c# - 从命令行传递参数时 Devenv 崩溃

c# - .NET 4.5 中未观察到的任务异常仍然会导致应用程序崩溃

c# - 两种不相等的类型应该是

c# - 如何将泛型类型参数限制为 System.Enum

c# - 如何保护将重要数据发布到我的数据库的公共(public) ASMX 页面