Gre*_*som 205 .net c# wpf multithreading task
是否有一种"标准"方式来指定任务延续应该在创建初始任务的线程上运行?
目前我有下面的代码 - 它正在工作,但跟踪调度程序和创建第二个动作似乎是不必要的开销.
dispatcher = Dispatcher.CurrentDispatcher;
Task task = Task.Factory.StartNew(() =>
{
DoLongRunningWork();
});
Task UITask= task.ContinueWith(() =>
{
dispatcher.Invoke(new Action(() =>
{
this.TextBlock1.Text = "Complete";
}
});
Run Code Online (Sandbox Code Playgroud)
Gre*_*som 336
用以下方式调用延续TaskScheduler.FromCurrentSynchronizationContext()
:
Task UITask= task.ContinueWith(() =>
{
this.TextBlock1.Text = "Complete";
}, TaskScheduler.FromCurrentSynchronizationContext());
Run Code Online (Sandbox Code Playgroud)
仅当当前执行上下文位于UI线程上时,这才适用.
Joh*_*son 31
使用异步你只需:
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);
Run Code Online (Sandbox Code Playgroud)
然而:
await Task.Run(() => do some stuff).ConfigureAwait(false);
// continue doing stuff on the same thread as the task finished on.
Run Code Online (Sandbox Code Playgroud)
Sim*_*ver 21
如果您有需要发送到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());
Run Code Online (Sandbox Code Playgroud)
Dea*_*ean 12
我只是想添加这个版本,因为这是一个非常有用的线程,我认为这是一个非常简单的实现.如果多线程应用程序我在各种类型中多次使用它:
Task.Factory.StartNew(() =>
{
DoLongRunningWork();
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
{ txt.Text = "Complete"; }));
});
Run Code Online (Sandbox Code Playgroud)
通过谷歌来到这里,因为我正在寻找一种在 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;
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
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;
}
}
Run Code Online (Sandbox Code Playgroud)