[英]Task continuation on UI thread
是否有一種“標准”方法來指定任務繼續應該在創建初始任務的線程上運行?
目前我有下面的代碼 - 它正在工作,但跟蹤調度程序並創建第二個 Action 似乎是不必要的開銷。
dispatcher = Dispatcher.CurrentDispatcher;
Task task = Task.Factory.StartNew(() =>
{
DoLongRunningWork();
});
Task UITask= task.ContinueWith(() =>
{
dispatcher.Invoke(new Action(() =>
{
this.TextBlock1.Text = "Complete";
}
});
使用TaskScheduler.FromCurrentSynchronizationContext()
調用延續:
Task UITask= task.ContinueWith(() =>
{
this.TextBlock1.Text = "Complete";
}, TaskScheduler.FromCurrentSynchronizationContext());
這僅適用於當前執行上下文在 UI 線程上的情況。
使用異步,您只需執行以下操作:
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.
如果你有一個返回值,你需要發送到 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());
我只是想添加這個版本,因為這是一個非常有用的線程,我認為這是一個非常簡單的實現。 如果多線程應用程序,我在各種類型中多次使用它:
Task.Factory.StartNew(() =>
{
DoLongRunningWork();
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
{ txt.Text = "Complete"; }));
});
通過谷歌到達這里是因為我正在尋找一種在進入 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) ...
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.