是否有'标准'方法来指定任务延续应该在创建初始任务的线程上运行?
目前我有以下代码 - 它正在运行,但跟踪调度程序并创建第二个Action似乎是不必要的开销。
dispatcher = Dispatcher.CurrentDispatcher;
Task task = Task.Factory.StartNew(() =>
{
DoLongRunningWork();
});
Task UITask= task.ContinueWith(() =>
{
dispatcher.Invoke(new Action(() =>
{
this.TextBlock1.Text = "Complete";
}
});
答案 0 :(得分:319)
使用TaskScheduler.FromCurrentSynchronizationContext()
:
Task UITask= task.ContinueWith(() =>
{
this.TextBlock1.Text = "Complete";
}, TaskScheduler.FromCurrentSynchronizationContext());
仅当当前执行上下文位于UI线程上时才适用。
答案 1 :(得分:29)
您只需执行异步操作:
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.
答案 2 :(得分:19)
如果你有一个返回值,你需要发送到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());
答案 3 :(得分:11)
我只是想添加这个版本,因为这是一个非常有用的线程,我认为这是一个非常简单的实现。如果是多线程应用程序,我已经多次使用过多次:
Task.Factory.StartNew(() =>
{
DoLongRunningWork();
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
{ txt.Text = "Complete"; }));
});
答案 4 :(得分:3)
通过google进入这里,因为我一直在寻找一种在Task.Run调用后在ui线程上做事的好方法-使用以下代码,您可以使用await
返回UI线程再次。
我希望这对某人有帮助。
public static class UI
{
public static DispatcherAwaiter Thread => new DispatcherAwaiter();
}
public struct DispatcherAwaiter : INotifyCompletion
{
public bool IsCompleted => Application.Current.Dispatcher.CheckAccess();
public void OnCompleted(Action continuation) => Application.Current.Dispatcher.Invoke(continuation);
public void GetResult() { }
public DispatcherAwaiter GetAwaiter()
{
return this;
}
}
用法:
... code which is executed on the background thread...
await UI.Thread;
... code which will be run in the application dispatcher (ui thread) ...