I recently came across a strange bug in my async code. I was calling a blocking method on a COM control, which appeared to allow my async continuations to run while it was blocking.
Consider example code (illustrative purposes only)
public async void Main()
{
//assume some single threaded dispatcher. eg. WpfDispatcher
Task doAsyncTask = DoAsync();
Console.WriteLine("Start synchronous");
CallSomeCOMControl();
Console.WriteLine("End synchronous");
await doAsyncTask;
}
public async Task DoAsync()
{
Console.WriteLine("Start async");
await Task.Delay(1);
Console.WriteLine("End async");
}
In normal circumstances I would expect the following output:
Start async
Start synchronous
End synchronous
End async
What I was effectively seeing was:
Start async
Start synchronous
End async
End synchronous
Now I do not have the source for the COM control, but I do know that is a very old C++ control that has no notion of async/await. It is however an Active-X control.
I do not know the implementation details of the .Net RCW, but I am assuming that some kind of message pumping must be going on to allow the control to work. I am also assuming that this pumping is allowing my continuations to run.
Are my assumptions correct? And are the any other circumstances that I should be aware of where my supposedly synchronous code could get interrupted?
This is pretty normal, COM will pump when the call crosses an apartment boundary. It has to pump, not doing so is very likely to cause deadlock. It is unclear why that boundary has to be crossed from the snippet, it looks like an STA thread when you talk about WPF. Could be an out-of-process server, could be that you created the object on a worker thread.
It is not fundamentally different from the way the CLR will pump on a WaitOne() or Join() call when you block an STA thread. The re-entrancy headaches that this causes are pretty similar to the kind of misery caused by DoEvents(). Both COM and the CLR pump selectively though, not quite as dangerous. Albeit highly undocumented.
COM apartments greatly simplify threading, taking care of 98% of the usual problems. The last 2% give you a splitting migraine that can be exceedingly hard to solve, re-entrancy is on the top of that list. Only way to address that is to not leave it up to COM to provide the component with a thread-safe home and take care of it yourself. With code like this.
Independently of being awaited or not, the task returned from DoAsync has already started when the method returns.
And you are using a delay of just 1 millisecond.
Have you tried a larger delay?
Related
It seems it is impossible in c# (dotnet core 3.1) to call an asynchronous function from a non-async method without blocking the original thread. Why ?
Code example:
public async Task myMethodAsync() {
await Task.Delay(5000);
}
public void callingMethhod() {
myMethodAsync().Wait(); // all flavours of this expression, like f.ex. .Result seem to be blocking the calling thread
}
What is the technical limitation for being able to release the calling thread until the async method completes, and then continue execution from there? Is it something technically impossible?
Yes, that is expected. That is why the concept of Task etc exist. If it was possible to do what you want: they wouldn't need to - we could just wave a wand and everything would be async. The entire point of awaitable types is that releasing the calling thread while allowing later continuation is hard, and requires coordination and participation from the calling code; and from what ever calls that; etc - all the way up the stack to whatever is running the threads. Your callingMethhod code is synchronous: it has only a few things it can do:
it can run to completion - meaning: it would have to block
it can throw an exception
The impact of this is that async/await is infectious; anything that touches awaitables kinda needs to also be awaitable, which means: you would typically only call myMethodAsync from a callingMethhod that returned a [Value]Task[<T>], and which is presumably async with an await (although those bits aren't strictly necessary in the example shown).
It seems it is impossible in c# (dotnet core 3.1) to call an asynchronous function from a non-async method without blocking the original thread. Why ?
Because that's what synchronous means. Synchronous means it blocks the thread until the method is complete.
What is the technical limitation for being able to release the calling thread until the async method completes, and then continue execution from there? Is it something technically impossible?
If your calling method wants to release its thread, then make it asynchronous. Asynchronous methods are capable of releasing their calling threads. There's nothing impossible here; it's been solved by async and await.
Now, if you're asking "why can't every method implicitly be async", then that is in theory possible, but it causes a couple of major issues. It can never be done in C# for backwards compatibility reasons. The two issues that immediately come to mind are:
Limited interop. It's not possible to use an "everything is async" language to interop with anything that uses old-school threading (Win32 mutexes, et. al.).
Unexpected concurrency. There are a lot of scenarios where developers make an assumption of synchronous code. If every method is potentially asynchronous, then even code as simple as var x = this._list[0]; this._list.RemoveAt(0); is no longer safe.
Suppose (entirely hypothetically ;)) I have a big pile of async code.
10s of classes; 100s of async methods, of which 10s are actually doing async work (e.g. where we WriteToDbAsync(data) or we ReadFileFromInternetAsync(uri), or when WhenAll(parallelTasks).
And I want to do a bunch of diagnostic debugging on it. I want to perf profile it, and step through a bunch of it manually to see what's what.
All my tools are designed around synchronous C# code. They will sort of work with async, but it's definitely much less effective, and debugging is way harder, even when I try to directly manage the threads a bit.
If I'm only interested in a small portion of the code, then it's definitely a LOT easier to temporarily un-async that portion of the code. Read and Write synchronously, and just Task.Wait() on each of my "parallel" Tasks in sequence. But that's not viable for to do if I want to poke around in a large swathe of the code.
Is there anyway to ask C# to run some "async" code like that for me?
i.e. some sort of (() => MyAsyncMethod()).RunAsThoughAsyncDidntExist() which knows that any time it does real async communication with the outside world, it should just spin (within the same thread) until it gets an answer. Any time it's asked to run code in parallel ... don't; just run them in series on its single thread. etc. etc.
I'm NOT talking about just awaiting for the Task to finish, or calling Task.Wait(). Those won't change how that Task executes itself
I strongly assume that this sort of thing doesn't exist, and I just have to live with my tools not being well architected for async code.
But it would be great if someone with some expertise in the area, could confirm that.
EDIT: (Because SO told me to explain why the suggestion isn't an answer)...
Sinatr suggested this: How do I create a custom SynchronizationContext so that all continuations can be processed by my own single-threaded event loop? but (as I understand it) that is going to ensure that each time there's an await command then the code after that await continues on the same thread. But I want the actual contents of the await to be on the same thread.
Keep in mind that asynchronous != parallel.
Parallel means running two or more pieces of code at the same time, which can only be done with multithreading. It's about how code runs.
Asynchronous code frees the current thread to do other things while it is waiting for something else. It is about how code waits.
Asynchronous code with a synchronization context can run on a single thread. It starts running on one thread, then fires off an I/O request (like an HTTP request), and while it waits there is no thread. Then the continuation (because there is a synchronization context) can happen on the same thread depending on what the synchronization context requires, like in a UI application where the continuation happens on the UI thread.
When there is no synchronization context, then the continuation can be run on any ThreadPool thread (but might still happen on the same thread).
So if your goal is to make it initially run and then resume all on the same thread, then the answer you were already referred to is indeed the best way to do it, because it's that synchronization context that decides how the continuation is executed.
However, that won't help you if there are any calls to Task.Run, because the entire purpose of that method is to start a new thread (and give you an asynchronous way to wait for that thread to finish).
It also may not help if the code uses .ConfigureAwait(false) in any of the await calls, since that explicitly means "I don't need to resume on the synchronization context", so it may still run on a ThreadPool thread. I don't know if Stephen's solution does anything for that.
But if you really want it to "RunAsThoughAsyncDidntExist" and lock the current thread while it waits, then that's not possible. Take this code for example:
var myTask = DoSomethingAsync();
DoSomethingElse();
var results = await myTask;
This code starts an I/O request, then does something else while waiting for that request to finish, then finishes waiting and processes the results after. The only way to make that behave synchronously is to refactor it, since synchronous code isn't capable of doing other work while waiting. A decision would have to be made whether to do the I/O request before or after DoSomethingElse().
I need to make sure some of my code runs in the background and doesn't stop block the UI thread, and I thought I knew how to use Task.Factory.New, but as I read more and more, it seems that it doesn't always create a new thread but sometimes runs it on the UI thread if the thread pool thinks that's the way to go so now I am pretty confused over what to use to be safe that the method is not blocking the UI thread. I should also add that I don't need a return value from the method , I just need it to run asynchronously ( in the background ).
So what's the difference between these methods below and what is best to use to make sure it doesn't block the UI thread ?
And is it really true that Task.Factory.StartNew doesn't always create a thread that runs in the background and doesn't block the UI?
public Form1()
{
Task.Factory.StartNew(() => Thread.Sleep(1000));
Task.Run(() => Thread.Sleep(1000));
Task<int> longRunningTask = LongRunningOperationAsync();
}
public async Task<int> LongRunningOperationAsync() // assume we return an int from this long running operation
{
await Task.Delay(1000);
return 1;
}
I should also add that I don't need a return value from the method
Beware of a common problem: just because you don't need a return value doesn't mean you shouldn't await the returned task. awaiting the task provides you with exception information as well. The only time it's appropriate to ignore the returned task is when you don't care about the return value and you don't care about any exceptions the background work may raise (that is, you're OK with silently swallowing them).
In easily >99% of cases, the appropriate behavior is to await the task.
So what's the difference between these methods below
StartNew is an outdated way to run code on a thread pool thread. You should use Run instead of StartNew. I describe why in painful detail on my blog, but the short answer is that StartNew does not understand async delegates and has inappropriate default options.
async is completely different. Run executes code on a thread pool thread, but async rewrites the code so that it doesn't need a thread while there's an asynchronous operation in progress. So, the Run example will block a thread pool thread for 1000ms in the Thread.Sleep call. The async example will run on the UI thread and then not use the UI thread for 1000ms in the await Task.Delay call.
and what is best to use to make sure it doesn't block the UI thread?
Both Task.Run and async are appropriate in UI apps, depending on the nature of the background code.
If your code is asynchronous (usually all I/O-bound code), then you should use async/await. Note that imposing asynchrony "top-down" is hard. Don't think about "forcing code off the UI thread"; instead, identify the naturally-asynchronous parts of your system (DB, file, WebAPI calls, etc), change them to be async at the lowest level, and work up from there.
If your code is synchronous (CPU-bound), then you can use Task.Run if it takes too long to run on your UI thread.
And is it really true that Task.Factory.StartNew doesn't always create a thread that runs in the background and doesn't block the UI?
Run always executes code on threads from the thread pool. The rules for StartNew are much more complex, but in your example example code, if TaskScheduler.Current == TaskScheduler.Default, then StartNew will also use a thread from the thread pool.
The two examples you give are pretty much the same and depend of the context you are using them on.
Tasks are a way to describe a packet of work with meta information to know about its state, synchronize multiple tasks, cancel them etc. The main idea about tasks and asynchronicity is that you don't have to care about "where" (on which thread) this unit of work is executed, it is performed asynchronously, that's all you need to know. So no worries for your UI-Thread, as long as you are working asynchronously, it won't be locked (that's one of the main improvements since Win8 and the async/await keywords, every UI Manipulation has to be async not to bloat the UI).
As for async&await, those are in fact syntactic sugar. In many simple cases, you don't need to care about the task itself, you just want the asynchronous computation "do this and give me the answer when you have it".
int x = await ComputeXAsync(); //Returns a Task<int> which will be automatically unwrapped as an int
If you need to synchronize tasks, for example start multiple tasks in parallel and wait that all of them are done before continuing, you can't rely on the simple await Task<int> format, you then need to work with the task itself, its Status property and in this case the Task.WaitAll(task[]) API.
Edit: I really recommend the chapter of JonSkeets Book C# in Depth (last edition). The Async/Await part is really well explained and will take you way further than any reading online will do.
The first two are actually the same. see here
Well you can think of it as a task is something you want to be done.
A thread is something like a worker which does the task for you. So basically a threads helps you doing a task, but it doesn't return a value.
a task does not create its own OS thread. Instead, tasks are executed by a TaskScheduler; the default scheduler simply runs on the ThreadPool.
See Here
An example is. A remote request you can do as task, you want the job done but dont know when it will be. But a TCPListener for the server I would run as a thread, because it always needs to listen to the socket.
Like Andreas Niedermair pointed out, you can also use longliving tasks with the TaskCreationOptions
First a small bit of background information. I am in the process of making existing C# library code suitable for execution on WinRT. As a minor part of this code deep down needs to do a little file IO, we first tried to keep things synchronous and used Task.Wait() to stop the main thread until all IO was done.
Sure enough, we quickly found out that leads to a deadlock.
I then found myself changing a lot of code in a prototype to make it "asynchronous". That is, I was inserting async and await keywords, and I was changing the method return types accordingly. This was a lot of work - too much senseless work in fact -, but I got the prototype working this way.
Then I did an experiment, and I ran the original code with the Wait statement on a separate thread:
System.Threading.Tasks.Task.Run(()=> Draw(..., cancellationToken)
No deadlock!
Now I am seriously confused, because I thought that I understood how async programming works. Our code does not (yet) use ConfigureAwait(false) at all. So all await statements should continue in the same context as they got invoked in. Right? I assumed that that means: the same thread. Now if this thread has invoked "Wait", this should also lead to a deadlock. But it does not.
Do any of you have a clear rock-solid explanation?
The answer to this will determine whether I will really go through messing up our code by inserting a lot of conditional async/await keywords, or whether I will keep it clean and just use a thread that does a Wait() here and there. If the continuations get run by an arbitrary non-blocked thread, things should be fine. However, if they get run by the UI thread, we may be in trouble if the continuation is computationally expensive.
I hope that the issue is clear. If not, please let me know.
I have an async/await intro on my blog, where I explain exactly what the context is:
It is SynchronizationContext.Current, unless it is null, in which case it is TaskScheduler.Current. Note: if there is no current TaskScheduler, then TaskScheduler.Current is the same as TaskScheduler.Default, which is the thread pool task scheduler.
In today's code, it usually just comes down to whether or not you have a SynchronizationContext; task schedulers aren't used a whole lot today (but will probably become more common in the future). I have an article on SynchronizationContext that describes how it works and some of the implementations provided by .NET.
WinRT and other UI frameworks (WinForms, WPF, Silverlight) all provide a SynchronizationContext for their main UI thread. This context represents just the single thread, so if you mix blocking and asynchronous code, you can quickly encounter deadlocks. I describe why this happens in more detail in a blog post, but in summary the reason why it deadlocks is because the async method is attempting to re-enter its SynchronizationContext (in this case, resume executing on the UI thread), but the UI thread is blocked waiting for that async method to complete.
The thread pool does not have a SynchronizationContext (or TaskScheduler, normally). So if you are executing on a thread pool thread and block on asynchronous code, it will not deadlock. This is because the context captured is the thread pool context (which is not tied to a particular thread), so the async method can re-enter its context (by just running on a thread pool thread) while another thread pool thread is blocked waiting for it to complete.
The answer to this will determine whether I will really go through messing up our code by inserting a lot of conditional async/await keywords, or whether I will keep it clean and just use a thread that does a Wait() here and there.
If your code is async all the way, it shouldn't look messy at all. I'm not sure what you mean by "conditional"; I would just make it all async. await has a "fast path" implementation that makes it synchronous if the operation has already completed.
Blocking on the asynchronous code using a background thread is possible, but it has some caveats:
You don't have the UI context, so you can't do a lot of UI things.
You still have to "sync up" to the UI thread, and your UI thread should not block (e.g., it should await Task.Run(..), not Task.Run(..).Wait()). This is particularly true for WinRT apps.
Basically, if I call an async method my application doesn't hang, I can click things and the such (if I allow it) without penalty. Once the async operation is complete, the callback method is executed.
I'm wondering if this blocks things again or is it still "asynchronous"? That is... say the callback method is extremely intensive, will my application still run nicely or is it blocked once the callback method is entered?
Update:
What I'm talking about are the methods created when you add a service reference and select "Async operations"
public void AsyncSaveFooCompleted(Object sender, SaveFooEventArgs e)
{
//Send a large binary from the WCF Service
Client.SaveFooBinary(Foo.LargeBinary);
}
public void SaveFoo(Foo foo)
{
Client.SaveFooAsync(foo);
}
You will have some kind of blocking if your callback is that intensive. If you are having this issue, move more of the processing in the async method and leave the callback nice and simple.
Alternatively, if you need to process this in stages, have the callback start another async process with a different callback.
The callback method should not be intensive. In my opinion your thread should handle its intensive processing and let to the callback just the rendering logic.
I'm assuming you're talking about C# 5 async methods...
The callback will execute on the UI thread by default. It sounds like you should put the expensive work into its own task (e.g. with TaskEx.Run), then await that... assuming the heavy processing doesn't have to execute on the UI thread. If you've fundamentally got a lot of work which has to be on the UI thread, there's not a great deal you can do about that.
Your question is kind of vague, because you don't explain how you are performing the async operation. If you are using the new async methods in C# 5.0 like Jon Skeet suggested, then follow his advice, but if not then the easiest way for you to test (however you are doing your async), is to throw some blocking code in the callback.
Something along the lines of Thread.Sleep(10000), and you will know in an instant whether your callback will block the UI thread or not. In all fairness though, your UI thread should never have "intensive" work unless the user cannot continue or do anything until the operation is complete because of some requirement of that task, then it doesn't really matter because the user has to wait in either circumstance. However, you could still consider this bad design because any UI with intensive work on the UI thread gets the infamous "Not Responding" and the user may thing your app has stopped working, even though its still executing the task.