首页 文章

UI线程上的任务继续

提问于
浏览
189

是否有一种“标准”方式来指定任务延续应该在创建初始任务的线程上运行?

目前我有下面的代码 - 它正在工作,但跟踪调度程序和创建第二个动作似乎是不必要的开销 .

dispatcher = Dispatcher.CurrentDispatcher;
Task task = Task.Factory.StartNew(() =>
{
    DoLongRunningWork();
});

Task UITask= task.ContinueWith(() =>
{
    dispatcher.Invoke(new Action(() =>
    {
        this.TextBlock1.Text = "Complete"; 
    }
});

5 回答

  • 10

    如果您有需要发送到UI的返回值,则可以使用如下通用版本:

    在我的例子中,这是从MVVM ViewModel调用的 .

    var updateManifest = Task<ShippingManifest>.Run(() =>
        {
            Thread.Sleep(5000);  // prove it's really working!
    
            // GenerateManifest calls service and returns 'ShippingManifest' object 
            return GenerateManifest();  
        })
    
        .ContinueWith(manifest =>
        {
            // MVVM property
            this.ShippingManifest = manifest.Result;
    
            // or if you are not using MVVM...
            // txtShippingManifest.Text = manifest.Result.ToString();    
    
            System.Diagnostics.Debug.WriteLine("UI manifest updated - " + DateTime.Now);
    
        }, TaskScheduler.FromCurrentSynchronizationContext());
    
  • 0

    我只是想添加这个版本,因为这是一个非常有用的线程,我认为这是一个非常简单的实现 . 如果多线程应用程序我在各种类型中多次使用它:

    Task.Factory.StartNew(() =>
          {
            DoLongRunningWork();
            Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
                  { txt.Text = "Complete"; }));
          });
    
  • 25

    使用 TaskScheduler.FromCurrentSynchronizationContext() 调用延续:

    Task UITask= task.ContinueWith(() =>
        {
         this.TextBlock1.Text = "Complete"; 
        }, TaskScheduler.FromCurrentSynchronizationContext());
    

    仅当当前执行上下文位于UI线程上时,这才适用 .

  • 19

    使用异步你只需:

    await Task.Run(() => do some stuff);
    // continue doing stuff on the same context as before.
    // while it is the default it is nice to be explicit about it with:
    await Task.Run(() => do some stuff).ConfigureAwait(true);
    

    然而:

    await Task.Run(() => do some stuff).ConfigureAwait(false);
    // continue doing stuff on the same thread as the task finished on.
    
  • 306

    J 你把代码编写为(但是使用 ContinueWith 是一个很好的做法,不要担心运行时不必要的开销)

    Task task = Task.Factory.StartNew(() =>
    {
        DoLongRunningWork();
        Dispatcher.CurrentDispatcher.BeginInvoke(new Action(() =>
        {
            this.TextBlock1.Text = "Complete"; 
        }
    });
    

    如果要确保要运行,请将Dispatcher代码放在finally块中 .

    Try Avoiding TaskScheduler.FromCurrentSynchronizationContext() 使用此功能您的UI Thread 可能会被您当前的 Thread 阻止 .

相关问题