How do I upgrade from Task the UI Thread?

I have a task that does the hard work. I need to pass the result to LogContent

 Task<Tuple<SupportedComunicationFormats, List<Tuple<TimeSpan, string>>>>.Factory .StartNew(() => DoWork(dlg.FileName)) .ContinueWith(obj => LogContent = obj.Result); 

This property:

 public Tuple<SupportedComunicationFormats, List<Tuple<TimeSpan, string>>> LogContent { get { return _logContent; } private set { _logContent = value; if (_logContent != null) { string entry = string.Format("Recognized {0} log file",_logContent.Item1); _traceEntryQueue.AddEntry(Origin.Internal, entry); } } } 

The problem is that _traceEntryQueue is data bound to the UI, and due to the reason I will have an exception from code like this.

So my question is how to make it work correctly?

+7
source share
4 answers

You need to run ContinueWith -task in the user interface thread. This can be done using the TaskScheduler UI thread with an overloaded version of the ContinueWith method i.e.

 TaskScheduler scheduler = TaskScheduler.Current; ...ContinueWith(obj => LogContent = obj.Result), CancellationToken.None, TaskContinuationOptions.None, scheduler) 
+5
source

Here's a good article: Parallel Programming: Task Schedulers and a Synchronization Context .

Take a look at the Task.ContinueWith () method .

Example:

 var context = TaskScheduler.FromCurrentSynchronizationContext(); var task = new Task<TResult>(() => { TResult r = ...; return r; }); task.ContinueWith(t => { // Update UI (and UI-related data) here: success status. // t.Result contains the result. }, CancellationToken.None, TaskContinuationOptions.OnlyOnRanToCompletion, context); task.ContinueWith(t => { AggregateException aggregateException = t.Exception; aggregateException.Handle(exception => true); // Update UI (and UI-related data) here: failed status. // t.Exception contains the occured exception. }, CancellationToken.None, TaskContinuationOptions.OnlyOnFaulted, context); task.Start(); 

Since .NET 4.5 supports the async / await keywords (see also Task.Run vs Task.Factory.StartNew ):

 try { var result = await Task.Run(() => GetResult()); // Update UI: success. // Use the result. } catch (Exception ex) { // Update UI: fail. // Use the exception. } 
+16
source

You can use Dispatcher to invoke code in the user interface thread. Take a look at the article Working with WPF Manager

+1
source

If you are using async / await, here is an example code that shows how to schedule a task to run in a GUI thread. Put this code at the bottom of the stack of all your async / await calls to avoid errors when starting WPF with code that does not execute in the GUI thread.

Works with WPF + MVVM tested in VS 2013.

 public async Task GridLayoutSetFromXmlAsync(string gridLayoutAsXml) { Task task = new Task(() => // Schedule some task here on the GUI thread ); task.RunSynchronously(); await task; } 
0
source

All Articles