If I call RunSynchronously()
on a Task
in C#, will this lead to asynchronous calls further down the rabbit hole to be run synchronously as well?
Let's say I have a method named UpdateAsync()
. Inside this method another asynchronous call is made to DoSomethingAsync()
and inside this again we find DoSomethingElseAsync()
, will calling RunSynchronously()
on 'UpdateAsync()' lead to RunSynchronously()
also indirectly being called on DoSomethingAsync()
?
The reason for my question:
I have a situation where I "need" to call an asynchronous method (UpdateAsync()
) inside a catch
-block and wonder if calling this with RunSynchronously()
is safe. The documentation is quite clear on the fact that you can't await
inside a catch
-block. (Strictly speaking I could use a boolean inside the catch
-block and call UpdateAsync()
after the try-catch, but that feels rather dirty). Sorry about the dual question, but as you probably understand I don't quite know how to phrase it and do not have a really good understanding of this field.
(Edit:
I don't know how to find out if a method was called asynchronously. How would you write a unit test for this? Is it possible to log it somehow?)
I "need" to call an asynchronous method and wonder if calling this with RunSynchronously()
is safe
There are two kinds of Task
s: code-based* Tasks
(you can create those by using the Task
constructor or Task.Factory.StartNew()
) and promise-style Task
s (you can create them manually by using TaskCompletionSource
or by writing an async
method).
And the only Task
s that you can start by calling Start()
or RunSynchronously()
are unstarted code-based Task
s. Since async methods return promise-style Task
s (or possibly already started code-based Task
s), calling RunSynchronously()
on them is not valid and will result in an exception.
So, to actually answer your question: what you're asking isn't possible, so it doesn't make sense to ask whether it's safe.
* This is not an official name, I don't know if there is one.
It's hard to predict without code how it will execute nested async methods.
You can log on each async method Thread.CurrentThread.ManagedThreadId property and compare id with other thread IDs that you have. When they vary, then your async methods are in multithreaded executtion
Or try to use Concurrency Visualizer from Visual Studio, Analyze menu. With Task class instances and even with C#5 async syntax there is no way to get to know that you are executing in parallel or another thread.
I think I'll be contradicting @svick's answer, but I feel the OP question is valid, because an async method's "promised" (to use Svick's terminology) Task can be obtained, but not started, thus allowing to do Task.RunSynchronously()
.
static void Main(string[] args)
{
...
//obtain a Task that's not started
var t = new Task<int>((ob) => GetIntAsync((string)ob).Result, someString);
...
}
static async Task<int> GetIntAsync(string callerThreadId)
{
...
Having said that, the answer is: No, the RunSynchronously()
affects the task you run this on. If the call chain later contains more async calls, they run asynchronously.
I have a little console app that is modeling this, is someone is interested in seeing it, but the concept is pretty simple to reproduce - just chain enough asynchronous calls and toggle between running the earliest one synchronously and asynchronously to see the different behavior.