【问题标题】:Tasks, BackgroundWorkers or new Threads for database transactions in WPF MVVM?WPF MVVM 中数据库事务的任务、BackgroundWorkers 还是新线程?
【发布时间】:2012-12-20 14:48:34
【问题描述】:

我有一个与数据库通信的小型 MVVM 应用程序。在完成后更新 UI 的后台线程中执行数据库事务的标准方法是什么(如果有)?我应该使用 BackgroundWorkers、TPL 还是实现自己的线程?目前我有一个静态类,使用以下方法进行后台工作:

public static void RunAsync(Action backgroundWork, Action uiWork, Action<Exception> exceptionWork) {

    var uiContext = TaskScheduler.FromCurrentSynchronizationContext();

    // The time consuming work is run on a background thread.
    var backgroundTask = new Task(() => backgroundWork());

    // The UI work is run on the UI thread.
    var uiTask = backgroundTask.ContinueWith(_ => { uiWork(); },
        CancellationToken.None,
        TaskContinuationOptions.OnlyOnRanToCompletion,
        uiContext);

    // Exceptions in the background task are handled on the UI thread.
    var exceptionTask = backgroundTask.ContinueWith(t => { exceptionWork(t.Exception); },
        CancellationToken.None,
        TaskContinuationOptions.OnlyOnFaulted,
        uiContext);

    // Exceptions in the UI task are handled on on the UI thread.
    var uiExceptionTask = uiTask.ContinueWith(t => { exceptionWork(t.Exception); },
        CancellationToken.None,
        TaskContinuationOptions.OnlyOnFaulted,
        uiContext);

    backgroundTask.Start();
}

【问题讨论】:

    标签: c# wpf mvvm task


    【解决方案1】:

    你可以使用async/await,它会给你一个更自然的语法:

    public static async Task RunAsync(Action backgroundWork, Action uiWork, Action<Exception> exceptionWork)
    {
      try
      {
        // The time consuming work is run on a background thread.
        await Task.Run(backgroundWork);
    
        // The UI work is run on the UI thread.
        uiWork();
      }
      catch (Exception ex)
      {
        // Exceptions in the background task and UI work are handled on the UI thread.
        exceptionWork(ex);
      }
    }
    

    或者更好的是,只需将 RunAsync 替换为代码本身,而不是

    T[] values;
    RunAsync(() => { values = GetDbValues(); }, () => UpdateUi(values), ex => UpdateUi(ex));
    

    你可以说:

    try
    {
      var values = await Task.Run(() => GetDbValues());
      UpdateUi(values);
    }
    catch (Exception ex)
    {
      UpdateUi(ex);
    }
    

    【讨论】:

    • 谢谢,这正是我想要的!
    【解决方案2】:

    您可以使用这些技术中的任何一种。不过,我总是会在单独的线程上运行它们。重要的是线程操作在适当的时候被编组回 UI 线程。如果在 .net 4.5 中,我的偏好是使用任务或异步等待

    【讨论】:

    • await 的优点是在等待异步操作时不会阻塞线程。
    猜你喜欢
    • 2011-09-29
    • 2010-11-02
    • 1970-01-01
    • 1970-01-01
    • 2019-06-08
    • 2014-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多