nUnit Assert.That delegate concurrency issue - c#

I am experiencing some temporary dead lock in my code and can't wrap my head around it.
Simple code (I cannot create a simple call chain to reproduce the code in InvokeChangeEvent)
[Test]
public async void Test()
{
sut.InvokeChangeEvent("./foo.file");
// Event is handled by an async handler chaining multiple await resulting in a file write
// await Task.Delay(3000);
Assert.That(() => Directory.GetFiles("some dir").Count(), Is.EqualTo(3).After(15000, 300));
}
I am aware that y'all (:D) want executable code but I wasn't able to slice it down therefore I hope for some insight by explanation.
What happens: sut.InvokeChangeEvent calls an event handler that later calls an async event handler which then calls some async. The end of the chain results in an Task.Run that boils down to write 3 files.
The Assert above is implemented as a delegate with After that returns a DelayedConstraint and has a very large max time (15 secs) and a small polling interval.
Now when I debug the code the InvokeChangeEvent call is entirely executed to the last Task.Run but when the Task.Run returns, the execution is yielded back to the main thread and the Assert is executed entering the "wait with polling".
However the assert never succeeds. When I debug the issue the return of the Task.Run is always handled after the Assert delegate has run (and failed).
I've figured out, that when I place an await Task.Delay(3000); before the Assert, then the code executes properly.
As mentioned the system under test has plenty await and Task.Runs chained and I was unable to reproduce the issue with some easy runnable code.
I've been googling around for a while and I cannot figure out why the Task.Run (which is executed on a different thread) yield in a (temporary) deadlock even though the DelayedConstraint has an explicit polling interval to allow the main thread to progress.
It looks like the DelayedConstraint locks the main thread by some sort of Thread.Sleep. await Task.Delay does not, I am aware of that. What confuses me is I have checked that I always do an await (and never Task.Result, etc) and therefore would expect that the file has been written before the Assert has executed.
(Note: Thread.Sleep instead of await Task.Delay does not work.)
Usually the DelayedConstraint is used to ensure that file system has properly written all files as I have experienced some delays of the file system dealing with files.
I have some feeling that async void event handler may create a situation which I do not understand.
If I manage to create a simple sample, I will update the thread.

By analogy with VS2012 unit testing, try async Task signature rather than async void for your test method. This way, NUnit should be able to keep track of the pending task status and inspect exceptions via Task.Exception.
The async void method is a fire-and-forget concept, by definition. The method returns instantly (precisely, upon the first asynchronous await inside it), and then there is no way to handle its completion or any errors possibly thrown inside it. As is, async void methods are only good for event handlers, provided exceptions are handled within the method with try/catch.

Related

C# Asynchronous call "invoke and forget"

In c# when you invoke the await method inside an async method, the code will be executed from the calling context to that method. What if I want to make an asynchronous call which will just continue from the same line of code directly (even if the asynchronous action did not finish yet) instead of getting back to the calling context? How can I do that?
What if I want to make an asynchronous call which will just continue from the same line of code directly (even if the asynchronous action did not finish yet) instead of getting back to the calling context? How can I do that?
The easiest way, which works whether Something is synchronous or asynchronous:
var _ = Task.Run(() => Something());
But, as Eric Lippert stated:
it is a strange thing to get a task and then not care about what happens when it completes.
Or, as I like to put it: fire-and-forget is almost never what you really want. To "forget" means:
You don't care when it completes.
You don't care whether it completes. E.g., if your app exits (or app pool is recycled if on ASP.NET), then your background work is just lost.
You don't care whether it completes successfully. E.g., if your work throws an exception, you want to silently swallow that exception.
In real-world code, this scenario is extremely rare.
An await is, by definition, a point at which you must asynchronously wait for the task to finish before continuing the workflow. If you don't have to wait, then don't wait! There is no requirement that you await anything.
Your question is rather like asking "I have an IEnumerable<int> but I don't care what integers are in it; do I have to foreach over it?" No, you don't. If you don't care what the result is, you don't have to get a result from a sequence. If you don't care what the result of a task is, you don't have to await it.
But it is a strange thing to get a sequence and then not enumerate it, and it is a strange thing to get a task and then not care about what happens when it completes.
If you want to start the async method and continue inside the function you can do something like Task<string> getStringTask = asyncMethodThatReturnsString();. Then continue until you want to wait for the async task to finish at which point you would call string output = await getStringTask;.

Why is an exception swallowed in an async action in a constructor?

I thought I was being clever in finding a way to call an aync method in a ctor:
public AppStateModel(IBranchClient branchClient)
{
_branchClient = branchClient;
var loadBranch = new Action(async () =>
{
DataProviderReadResult<BranchDetailViewModel> result = await _branchClient.ReadOneItemAsync(AppSettings.BranchId, _initCts.Token);
});
loadBranch();
}
But the body of the action throws an exception, which I log and re-throw with plain throw;, but this ctor executes fine and the rest of my code continues running as if nothing happens. Why is this?
Because the action is asynchronous. loadBranch() returns as soon as the first await is reached, and can't possibly throw the exception you're expecting - that's part of the information in the Task that you've ignored (by using Action instead of Func<Task>).
All in all, you've just written a more obfuscated version of this:
_branchClient.ReadOneItemAsync(AppSettings.BranchId, _initCts.Token);
.NET constructors are inherently synchronous. They shouldn't be doing anything where you'd benefit from using asynchronous code - and it's a good idea to do as little as possible in a constructor (or methods called by the constructor). If you need complex actions, asynchronous code, I/O, lots of CPU work... use a static method. And since you're running asynchronous code, make it return a Task<AppStateModel>, fitting properly in the whole asynchronous flow.
Also note that the exception will not be swallowed on older .NET runtimes. Assuming there's no synchronization context, the exception is still thrown on a background thread (where the continuation to the asynchronous operation is posted) - and the default for unhandled exceptions on thread-pool threads used to be "bring down the whole application". This would happen when the Task object was being finalized, so decoupled from all your program logic, pretty much random as far as you can tell. After all, what else can you do - there's no good place where the exception could be observed, and the only root there ever was basically said "I don't care about what happens with this task". But given how complicated it was to ensure that every single exception is properly observed and handled, the default was changed to "unobserved exceptions are ignored".
Let's deconstruct what happens here: You have an Action delegate that points to an anonymous async void method. What does async void mean? It means that the method actually returns a Task that encapsulates the async logic.
What it means is that when you call loadBranch, it executes an async method. When the async method hits the await call, it returns a Task object that allows you to wait on it, add a continuation, or whatever. But since you don't have an explicit Task variable to capture it, you just let your constructor go out of scope, without any code handling the continuation of the Task. This means that when the Task throws, the ctor has already exited.

await Task.Run vs await

I've searched the web and seen a lot of questions regarding Task.Run vs await async, but there is this specific usage scenario where I don't not really understand the difference. Scenario is quite simple i believe.
await Task.Run(() => LongProcess());
vs
await LongProcess());
where LongProcess is a async method with a few asynchronous calls in it like calling db with await ExecuteReaderAsync() for instance.
Question:
Is there any difference between the two in this scenario? Any help or input appreciated, thanks!
Task.Run may post the operation to be processed at a different thread. That's the only difference.
This may be of use - for example, if LongProcess isn't truly asynchronous, it will make the caller return faster. But for a truly asynchronous method, there's no point in using Task.Run, and it may result in unnecessary waste.
Be careful, though, because the behaviour of Task.Run will change based on overload resolution. In your example, the Func<Task> overload will be chosen, which will (correctly) wait for LongProcess to finish. However, if a non-task-returning delegate was used, Task.Run will only wait for execution up to the first await (note that this is how TaskFactory.StartNew will always behave, so don't use that).
Quite often people think that async-await is done by several threads. In fact it is all done by one thread.
See the addition below about this one thread statement
The thing that helped me a lot to understand async-await is this interview with Eric Lippert about async-await. Somewhere in the middle he compares async await with a cook who has to wait for some water to boil. Instead of doing nothing, he looks around to see if there is still something else to do like slicing the onions. If that is finished, and the water still doesn't boil he checks if there is something else to do, and so forth until he has nothing to do but wait. In that case he returns to the first thing he waited for.
If your procedure calls an awaitable function, we are certain that somewhere in this awaitable function there is a call to an awaitable function, otherwise the function wouldn't be awaitable. In fact, your compiler will warn you if you forget to await somewhere in your awaitable function.
If your awaitable function calls the other awaitable function, then the thread enters this other function and starts doing the things in this function and goes deeper into other functions until he meets an await.
Instead of waiting for the results, the thread goes up in his call stack to see if there are other pieces of code he can process until he sees an await. Go up again in the call stack, process until await, etc. Once everyone is awaiting the thread looks for the bottom await and continues once that is finished.
This has the advantage, that if the caller of your awaitable function does not need the result of your function, but can do other things before the result is needed, these other things can be done by the thread instead of waiting inside your function.
A call without waiting immediately for the result would look like this:
private async Task MyFunction()
{
Task<ReturnType>taskA = SomeFunctionAsync(...)
// I don't need the result yet, I can do something else
DoSomethingElse();
// now I need the result of SomeFunctionAsync, await for it:
ReturnType result = await TaskA;
// now you can use object result
}
Note that in this scenario everything is done by one thread. As long as your thread has something to do he will be busy.
Addition. It is not true that only one thread is involved. Any thread who has nothing to do might continue processing your code after an await. If you check the thread id, you can see that this id can be changed after the await. The continuing thread has the same context as the original thread, so you can act as if it was the original thread. No need to check for InvokeRequired, no need to use mutexes or critical sections. For your code this is as if there is one thread involved.
The link to the article in the end of this answer explains a bit more about thread context
You'll see awaitable functions mainly where some other process has to do things, while your thread just has to wait idly until the other thing is finished. Examples are sending data over the internet, saving a file, communicating with a database etc.
However, sometimes some heavy calculations has to be done, and you want your thread to be free to do something else, like respond to user input. In that case you can start an awaitable action as if you called an async function.
Task<ResultType> LetSomeoneDoHeavyCalculations(...)
{
DoSomePreparations()
// start a different thread that does the heavy calculations:
var myTask = Task.Run( () => DoHeavyCalculations(...))
// now you are free to do other things
DoSomethingElse();
// once you need the result of the HeavyCalculations await for it
var myResult = await myTask;
// use myResult
...
}
Now a different thread is doing the heavy calculations while your thread is free to do other things. Once it starts awaiting your caller can do things until he starts awaiting. Effectively your thread will be fairly free to react on user input. However, this will only be the case if everyone is awaiting. While your thread is busy doing things your thread can't react on user input. Therefore always make sure that if you think your UI thread has to do some busy processing that takes some time use Task.Run and let another thread do it
Another article that helped me: Async-Await by the brilliant explainer Stephen Cleary
This answer deals with the specific case of awaiting an async method in the event handler of a GUI application. In this case the first approach has a significant advantage over the second. Before explaining why, lets rewrite the two approaches in a way that reflects clearly the context of this answer. What follows is only relevant for event handlers of GUI applications.
private async void Button1_Click(object sender, EventArgs args)
{
await Task.Run(async () => await LongProcessAsync());
}
vs
private async void Button1_Click(object sender, EventArgs args)
{
await LongProcessAsync();
}
I added the suffix Async in the method's name, to comply with the guidlines. I also made async the anonymous delegate, just for readability reasons. The overhead of creating a state machine is minuscule, and is dwarfed by the value of communicating clearly that this Task.Run returns a promise-style Task, not an old-school delegate Task intended for background processing of CPU-bound workloads.
The advantage of the first approach is that guarantees that the UI will remain responsive. The second approach offers no such guarantee. As long as you are using the build-in async APIs of the .NET platform, the probability of the UI being blocked by the second approach is pretty small. After all, these APIs are implemented by experts¹. By the moment you start awaiting your own async methods, all guarantees are off. Unless of course your first name is Stephen, and your surname is Toub or Cleary. If that's not the case, it is quite possible that sooner or later you'll write code like this:
public static async Task LongProcessAsync()
{
TeenyWeenyInitialization(); // Synchronous
await SomeBuildInAsyncMethod().ConfigureAwait(false); // Asynchronous
CalculateAndSave(); // Synchronous
}
The problem obviously is with the method TeenyWeenyInitialization(). This method is synchronous, and comes before the first await inside the body of the async method, so it won't be awaited. It will run synchronously every time you call the LongProcessAsync(). So if you follow the second approach (without Task.Run), the TeenyWeenyInitialization() will run on the UI thread.
How bad this can be? The initialization is teeny-weeny after all! Just a quick trip to the database to get a value, read the first line of a small text file, get a value from the registry. It's all over in a couple of milliseconds. At the time you wrote the program. In your PC. Before moving the data folder in a shared drive. Before the amount of data in the database became huge.
But you may get lucky and the TeenyWeenyInitialization() remains fast forever, what about the second synchronous method, the CalculateAndSave()? This one comes after an await that is configured to not capture the context, so it runs on a thread-pool thread. It should never run on the UI thread, right? Wrong. It depends to the Task returned by SomeBuildInAsyncMethod(). If the Task is completed, a thread switch will not occur, and the CalculateAndSave() will run on the same thread that called the method. If you follow the second approach, this will be the UI thread. You may never experience a case where the SomeBuildInAsyncMethod() returned a completed Task in your development environment, but the production environment may be different in ways difficult to predict.
Having an application that performs badly is unpleasant. Having an application that performs badly and freezes the UI is even worse. Do you really want to risk it? If you don't, please use always Task.Run(async inside your event handlers. Especially when awaiting methods you have coded yourself!
¹ Disclaimer, some built-in async APIs are not properly implemented.
Important: The Task.Run runs the supplied asynchronous delegate on a ThreadPool thread, so it's required that the LongProcessAsync has no affinity to the UI thread. If it involves interaction with UI controls, then the Task.Runis not an option. Thanks to #Zmaster for pointing out this important subtlety in the comments.

Reentrancy in async/await?

I have a button which has an async handler which calls awaits on an async method. Here's how it looks like:
private async void Button1_OnClick(object sender, RoutedEventArgs e)
{
await IpChangedReactor.UpdateIps();
}
Here's how IpChangedReactor.UpdateIps() looks:
public async Task UpdateIps()
{
await UpdateCurrentIp();
await UpdateUserIps();
}
It's async all the way down.
Now I have a DispatcherTimer which repeatedly calls await IpChangedReactor.UpdateIps in its tick event.
Let's say I clicked the button. Now the event handler awaits on UpdateIps and returns to caller, this means that WPF will continue doing other things. In the meantime, if the timer fired, it would again call UpdateIps and now both methods will run simultaneously. So the way I see it is that it's similar to using 2 threads. Can race conditions happen? (A part of me says no, because it's all running in the same thread. But it's confusing)
I know that async methods doesn't necessarily run on separate threads. However, on this case, it's pretty confusing.
If I used synchronous methods here, it would have worked as expected. The timer tick event will run only after the first call completed.
Can someone enlighten me?
Since both calls run on the UI thread the code is "thread safe" in the traditional sense of - there wouldn't be any exceptions or corrupted data.
However, can there be logical race conditions? Sure. You could easily have this flow (or any other):
UpdateCurrentIp() - button
UpdateCurrentIp() - Timer
UpdateUserIps() - Timer
UpdateUserIps() - button
By the method names it seems not to really be an issue but that depends on the actual implementation of these methods.
Generally you can avoid these problems by synchronizing calls using a SemaphoreSlim, or an AsyncLock (How to protect resources that may be used in a multi-threaded or async environment?):
using (await _asyncLock.LockAsync())
{
await IpChangedReactor.UpdateIps();
}
In this case though, it seems that simply avoiding starting a new update when one is currently running is good enough:
if (_isUpdating) return;
_isUpdating = true;
try
{
await IpChangedReactor.UpdateIps();
}
finally
{
_isUpdating = false;
}
I can think of a number of ways to handle this issue
1 Do not handle it
Like i3arnon says it might not be a problem to have multiple calls to the methods running at the same time. It all depends on the implementation of the update methods. Just like you write, it's very much the same problem that you face in real, multi-threaded concurrency. If having multiple async operations running at once is not a problem for these methods, you can ignore the reentrancy issues.
2 Block the timer, and wait for running tasks to finish
You can disable the timer, och block the calls to the event handler when you know you have a async task running. You can use a simple state field, or any kind of locking/signaling primitive for this. This makes sure you only have a single operation running at a given time.
3 Cancel any ongoing async operations
If you want to cancel any async operations already running, you can use a cancellationtoken to stop them, and then start a new operation. This is described in this link How to cancel a Task in await?
This would make sense if the operation takes a long time to finish, and you want to avoid spending time to complete an operation that is already "obsolete".
4 Queue the requests
If it's important to actually run all the updates, and you need synchronization you can queue the tasks, and work them off one by one. Consider adding some sort of backpressure-handling if you go down this route...

Does Task.RunSynchronously() work "recursively"?

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 Tasks: code-based* Tasks (you can create those by using the Task constructor or Task.Factory.StartNew()) and promise-style Tasks (you can create them manually by using TaskCompletionSource or by writing an async method).
And the only Tasks that you can start by calling Start() or RunSynchronously() are unstarted code-based Tasks. Since async methods return promise-style Tasks (or possibly already started code-based Tasks), 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.

Categories