-3

Previously, found some code on stackOverflow that was really useful :

https://stackoverflow.com/a/15120092/858282

But it's forced me to use many 'Invoke's and 'new MethodInvoker's whenever I need to update the User Interface with the result of the Background tasks. Basically, I'm creating a Winforms app that needs data from a database, so data loading happens in the background.

What I'm finding easiest at present is to Queue Tasks that use the retrieved data, as they run after the data retrieval is complete [i.e. queueTask(getData); queueTask(useData)], and sometimes thats ok, but looking at the code I see TaskContinuationOptions, and I was wondering if any of those options allow the 'Next Queue Item' to return to running on the UI thread, or if I could set a callback on a task's completion? So I don't have to use as many Invokes to prevent cross threading errors.

tl;dr; Task.ContinueWith that automagically returns to UI thread or allows a callback to a method running on the UI thread.

https://msdn.microsoft.com/en-us/library/system.threading.tasks.taskcontinuationoptions(v=vs.110).aspx

Community
  • 1
  • 1
Ninjanoel
  • 2,864
  • 4
  • 33
  • 53
  • 3
    instead you should use async/wait when Tasks are involved, then you won't have to work with continuations. They are seldom needed anymore. But if you insist, use `TaskScheduler.FromCurrentSynchronizationContext` instead of `TaskScheduler.Default` – Peter Bons May 05 '17 at 12:50
  • 4
    By the way, deleting a question to get rid of comments of another user and then asking it directly again is not really desired behavior imho – Peter Bons May 05 '17 at 12:52
  • @PeterBons So I could mix TaskScheduler contexts? Like create a third version of 'QueueTask' that essential runs `prevTask.ContinueWith(action, cancelToken, TaskContinuationOptions.None, TaskScheduler.FromCurrentSynchronizationContext);` ? – Ninjanoel May 05 '17 at 12:54
  • @PeterBons I know :-( but once someone starts a discussion in a certain direction i've found that it just chases all other answerer away, so to speak, I've not done that before, but there is no delete comment option. – Ninjanoel May 05 '17 at 12:55
  • 2
    Hmm, you might want to capture the context first, so you have a reference to the UI context, see http://reedcopsey.com/2009/11/17/synchronizing-net-4-tasks-with-the-ui-thread/. Then the mixing should be fine. – Peter Bons May 05 '17 at 13:01
  • But if you want to queue work, and have them complete one by one and in order, you can also use the `ActionBlock`, see http://stackoverflow.com/questions/20355931/limiting-the-amount-of-concurrent-tasks-in-net-4-5/42158377#42158377 – Peter Bons May 05 '17 at 13:05

1 Answers1

-2

Answering my own question, after comments from @PeterBons.

Additonal code to add to answer at https://stackoverflow.com/a/15120092/858282

/// <summary>
/// as per http://reedcopsey.com/2009/11/17/synchronizing-net-4-tasks-with-the-ui-thread/
/// from UI, store and pass 'TaskScheduler.FromCurrentSynchronizationContext()' into this method to avoid the 
/// need for 'Invoke' to avoid cross threading UI exceptions
/// </summary>    
public Task<T> QueueTask<T>(Func<T> work, TaskScheduler tScheduler, CancellationToken cancelToken = default(CancellationToken))
{
  lock (key)
  {
    var task = previousTask.ContinueWith(t => work()
        , cancelToken == default(CancellationToken) ? CancellationToken.None : cancelToken
        , TaskContinuationOptions.None
        , tScheduler);
    previousTask = task;
    return task;
  }
}
Community
  • 1
  • 1
Ninjanoel
  • 2,864
  • 4
  • 33
  • 53