Search code examples
c#wpfmultithreadingasync-awaitdispatch

Await a thread wont work when dispatch inside of the thread


I'm running a Task in a new thread and want to wait for it to finish.

var a = "logic before the task starts";
await Task.Factory.StartNew(() => MyHugeFunction(_token), _token);
var b = "logic after the task is finished";

It worked perfectly until I started to dispatch inside of the thread with:

 await Application.Current.Dispatcher.BeginInvoke(new Action(async () =>
 {
    SomeLogic();
 }));

The task itself works, but the await for my running task isn't working anymore. As soon as I am dispatching in the thread, the var b will be assigned in the main thread.

I already have some workarounds but I just wondered if I'm doing something stupid or this is caused by other circumstances

I'm working with C# 8.0 and .Net Framework 4.7.2.


Solution

  • I'm running a Task in a new thread and want to wait for it to finish.

    You want to use Task.Run instead of StartNew for that. StartNew is a dangerous, low-level API that should almost never be used, and in the few cases where you should use it, you should always pass a TaskScheduler.

    await Application.Current.Dispatcher.BeginInvoke(new Action(async () =>

    Imma stop you right there. First, you're explicitly creating an Action delegate with async, which results in an async void method, which should be avoided. Next, using Dispatcher to do any kind of Invoke or BeginInvoke really shouldn't be done at all.

    Instead, use the Progress<T> type. This keeps your logic in your background thread, which can pass objects as updates to the UI thread, and the UI thread decides how to display those progress updates in the UI. Note the nice separation of concerns there, which tends to go out the window whenever people start using Dispatcher.

    Both StartNew and Dispatcher are commonly seen in SO answers and blogs, but they're suboptimal solutions regardless.