Continuación de la tarea en el hilo de la interfaz de usuario


¿Hay una forma 'estándar' de especificar que una continuación de tarea debe ejecutarse en el subproceso desde el que se creó la tarea inicial?

Actualmente tengo el código a continuación: está funcionando, pero realizar un seguimiento del despachador y crear una segunda Acción parece una sobrecarga innecesaria.

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

Task UITask= task.ContinueWith(() =>
{
    dispatcher.Invoke(new Action(() =>
    {
        this.TextBlock1.Text = "Complete"; 
    }
});
Author: Greg Sansom, 2010-12-02

5 answers

Llama a la continuación con TaskScheduler.FromCurrentSynchronizationContext():

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

Esto solo es adecuado si el contexto de ejecución actual está en el subproceso de la interfaz de usuario.

 299
Author: Greg Sansom,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-06-24 00:35:04

Con async solo tienes que hacer:

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);

Sin embargo:

await Task.Run(() => do some stuff).ConfigureAwait(false);
// continue doing stuff on the same thread as the task finished on.
 24
Author: Johan Larsson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-06-24 09:25:17

Si tiene un valor devuelto que necesita enviar a la interfaz de usuario, puede usar la versión genérica de esta manera:

Esto está siendo llamado desde un ViewModel MVVM en mi caso.

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());
 19
Author: Simon_Weaver,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-19 21:15:02

Solo quería agregar esta versión porque este es un hilo muy útil y creo que es una implementación muy simple. He utilizado esto varias veces en varios tipos si multithreaded aplicación:

 Task.Factory.StartNew(() =>
      {
        DoLongRunningWork();
        Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
              { txt.Text = "Complete"; }));
      });
 10
Author: Dean,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-09-22 03:50:48

Just escriba su código como ( Pero usar ContinueWith es una buena práctica, no se preocupe por la sobrecarga innecesaria para el tiempo de ejecución )

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

Ponga el código Dispatcher en el bloque finally si desea asegurarse de esto para correr.

Trate de Evitar TaskScheduler.FromCurrentSynchronizationContext() a partir de usar esto, su UI Thread puede ser bloqueada por su Thread actual.

 0
Author: Kylo Ren,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-12 08:26:01