4

I am using monotouch/Xamarin for an iOS app.

The documentation for Task.Run states:

Queues the specified work to run on the ThreadPool and returns a task handle for that work.

Which essentially indicates that it could run on any thread ThreadPool.

I want to do something like:

Task.Run(async () => await PerformTask());

but have it run on the main thread. Normally I would write it using BeginInvokeOnMainThread as follows:

BeginInvokeOnMainThread(async () => await PerformTask());

But I am doing this in shared code and do not want to use iOS specific calls. Is there a way for me to tell Task.Run() to invoke the action on the main thread?

Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104
Kostub Deshmukh
  • 2,852
  • 2
  • 25
  • 35

3 Answers3

9

If you want to run PerformTask in the current thread, instead of a thread pool thread, you simply need to not call Task.Run. Just use:

PerformTask();

and you're done. If you want to only continue executing the rest of the method when that task is done, then await it:

await PerformTask();

There is no reason to call Task.Run here for you, nor is there any reason to create a lambda that awaits the method for no particular reason (you could just call it directly if you wanted to start it from a thread pool thread).

Servy
  • 202,030
  • 26
  • 332
  • 449
  • One of my biggest dislikes with async/await and task is that they are lacking the feature "Execute on main". I want to do this later, but i want to do it at the next step of the main event loop (no need for locks). – Dabaus Sep 30 '21 at 17:15
  • @Dabaus That async methods capture and use the synchronization context means that they do that *by default*. You need to go out of your way to make them *not* do that. That's the whole point of this answer, so your comment confuses me. – Servy Sep 30 '21 at 17:18
2

If you want to run a task from the main thread you could use TaskSchedluer's method FromCurrentSynchronizationContext().

Task t = new Task(() =>
{
    ...
});
t.Start(TaskScheduler.FromCurrentSynchronizationContext());

This can be useful sometimes. However, if you want to use this technique to bypass thread checks (for example, modifying properties of form controls in a windows app), you should rethink your design. Use tasks for calculations or other non-UI operations and update the UI from the main thread.

Florin Florea
  • 51
  • 1
  • 3
1

Have a look at MainQueue.cs: https://gist.github.com/gering/0aa9750d3c7d14b856d0ed2ba98374a8

It is for Xamarin Forms applications. You have to call Init() from main thread once, but then you are able to ensure execution on main thread.

Gering
  • 3,010
  • 3
  • 21
  • 23