Existe-t-il un moyen "standard" d'indiquer qu'une poursuite de tâche doit être exécutée sur le thread à partir duquel la tâche initiale a été créée?
Actuellement, j'ai le code ci-dessous - cela fonctionne, mais garder une trace du répartiteur et créer une deuxième action semble être une surcharge inutile.
dispatcher = Dispatcher.CurrentDispatcher;
Task task = Task.Factory.StartNew(() =>
{
DoLongRunningWork();
});
Task UITask= task.ContinueWith(() =>
{
dispatcher.Invoke(new Action(() =>
{
this.TextBlock1.Text = "Complete";
}
});
Appelez la suite avec TaskScheduler.FromCurrentSynchronizationContext()
:
Task UITask= task.ContinueWith(() =>
{
this.TextBlock1.Text = "Complete";
}, TaskScheduler.FromCurrentSynchronizationContext());
Cela ne convient que si le contexte d'exécution actuel est sur le thread d'interface utilisateur.
Avec async, vous faites juste:
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);
Pourtant:
await Task.Run(() => do some stuff).ConfigureAwait(false);
// continue doing stuff on the same thread as the task finished on.
Si vous avez une valeur de retour que vous devez envoyer à l'interface utilisateur, vous pouvez utiliser la version générique comme ceci:
Ceci est appelé depuis un MVVM ViewModel dans mon cas.
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());
Je voulais juste ajouter cette version parce que c'est un fil tellement utile et je pense que c'est une implémentation très simple. Je l'ai utilisé plusieurs fois dans différents types si application multithread:
Task.Factory.StartNew(() =>
{
DoLongRunningWork();
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
{ txt.Text = "Complete"; }));
});