I am writing a simple metro app. However, the API blocks when accessing files. By blocking, I mean the programs waits forever. Creating/opening a file or folder should take at most a few seconds. In this case, it takes forever.
When I run the program, it never comes back from OnTest. Is it what you get.
I understand .Wait will wait for the creation of files and folders to finishe. Maybe that's not great design. However, that's not the point.
My question is:
Do you get the same behavior (blocks the program forever)
Is it what's supposed to happen or is it a bug in WinRT? (I am using the consumer preview)
If that's the expected behavior, why does it take forever?
Here is the XAML code:
<Button Click="OnTest">Test</Button>
Here is the C# code:
private async void OnTest(object sender, RoutedEventArgs e)
{
var t = new Cache("test1");
t = new Cache("test2");
t = new Cache("test3");
}
class Cache
{
public Cache(string name)
{
TestRetrieve(name).Wait();
}
public static async Task TestRetrieve(string name)
{
StorageFolder rootFolder = ApplicationData.Current.LocalFolder;
var _folder = await rootFolder.CreateFolderAsync(name, CreationCollisionOption.OpenIfExists);
var file = await _folder.CreateFileAsync("test.xml", CreationCollisionOption.OpenIfExists);
}
}
It blocks on the second call to new Cache("test2");
I have not attempted to run your program or reproduce your problem, but I can make an educated guess as to what is going on.
Suppose you wrote yourself the following to-do list:
Put a letter to mom in the mailbox.
Set the alarm to wake me up as soon as I've read her reply.
Go to sleep.
Check the mailbox for the reply.
Read the reply.
Now do everything on that list strictly in order from top to bottom. What happens?
The problem is not with the post office or with mom; they are picking up the letter you put in the mailbox, sending it to mom, mom is writing her reply and the post office is bringing it back to you. The problem is that you never get to the fourth step because you only can start the fourth step after you complete the fifth step and the alarm wakes you up. You'll sleep forever because you are essentially waiting for your future self to wake your present self up.
Eric, Thank you for the explanation.
You're welcome.
However, I am still confused as to why my code does not work.
OK, let's break it down. What does your program really do? Let's simplify:
void M()
{
Task tx = GetATask();
tx.Wait();
}
async Task GetATask()
{
Task ty = DoFileSystemThingAsync();
await ty;
DoSomethingElse();
}
First off: what is a task? A task is an object that represents (1) a job to be done, and (2) a delegate to the continuation of the task: the thing that needs to happen after the task is done.
So you call GetATask. What does it do? Well, the first thing it does is it makes a Task and stores it in ty. That task represents the job "start some operation on the disk, and notify the I/O completion thread when it is done".
What is the continuation of that task? What has to happen after that task is done? DoSomethingElse needs to be called. So the compiler transforms the await into a bunch of code that tells the task to ensure that DoSomethingElse is called when the task is done.
The moment that the continuation of the I/O task has been set, the method GetATask returns a task to the caller. What task is that? This is a different task than the task that got stored into ty. The task that is returned is the task that represents the job do everything that the method GetATask needs to do.
What is the continuation of that task? We don't know! That is up to the caller of GetATask to decide.
OK, so let's review. We have two task objects. One represents the task "go do this thing on the file system". It will be done when the file system does its work. It's continuation is "call DoSomething". We have a second task object that represents the job "do everything in the body of GetATask". It will be done after the call to DoSomethingElse returns.
Again: the first task will be complete when the file I/O succeeds. When that happens, the file I/O completion thread will send a message to the main thread saying "hey, that file I/O you were waiting for is done. I am telling you this because it is now time for you to call DoSomethingElse".
But the main thread is not examining its message queue. Why not? Because you told it to synchronously wait until everything in GetATask, including DoSomethingElse, is complete. But the message that is telling you to run DoSomethingElse now cannot be processed because you are waiting for DoSomethingElse to be complete.
Now is it clear? You are telling your thread to wait until your thread is done running DoSomethingElse before you check to see if "please call DoSomethingElse" is in the queue of work to be performed on this thread! You are waiting until you have read the letter from mom, but the fact that you are waiting synchronously means that you are not checking your mailbox to see if the letter has arrived.
Calling Wait is obviously wrong in this case because you are waiting for yourself to do something in the future, and that's not going to work. But more generally, calling Wait completely negates the entire point of being async in the first place. Just don't do that; it doesn't make any sense to say both "I want to be asynchronous" and "but I want to synchronously wait". Those are opposites.
You're using Wait() in the constructor of the Cache class. That's going to block until whatever is currently executing asynchronously has finished.
This is not the way to design this. Constructors and async do not make sense. Perhaps a factory method approach like this would work better:
public class Cache
{
private string cacheName;
private Cache(string cacheName)
{
this.cacheName = cacheName;
}
public static async Cache GetCacheAsync(string cacheName)
{
Cache cache = new Cache(cacheName);
await cache.Initialize();
return cache;
}
private async void Initialize()
{
StorageFolder rootFolder = ApplicationData.Current.LocalFolder;
var _folder = await rootFolder.CreateFolderAsync(this.cacheName, CreationCollisionOption.OpenIfExists);
var file = await _folder.CreateFileAsync("test.xml", CreationCollisionOption.OpenIfExists);
}
}
And then you use it like this:
await Task.WhenAll(Cache.GetCacheAsync("cache1"), Cache.GetCacheAsync("cache2"), Cache.GetCacheAsync("cache3"));
TestRetrieve(name).Wait();
You're telling it to block specifically by using the .Wait() call.
Remove the .Wait() and it shouldn't block anymore.
The existing answers provide very thorough explanations of why it blocks and code examples of how to make it not block, but these many be 'more information' than some users understand. Here is a simpler 'mechanics oriented' explanation..
The way the async/await pattern works, each time you await an async method, you are "attaching" that method's async context to the current method's async context. Imagine await as passing in a magic hidden paramater "context". This context-paramater is what allows nested await calls to attach to the existing async context. (this is just an analogy...the details are more complicated than this)
If you are inside an async method, and you call a method synchronously, that synchronous method doesn't get that magic hidden async context paramater, so it can't attach anything to it. It's then an invalid operation to create a new async context inside that method using 'wait', because the new context does not get attached to your thread's existing top-level async context (because you don't have it!).
Described in terms of the code-example, the TestRetrieve(name).Wait(); is not doing what you think it's doing. It's actually telling the current thread to re-enter the async-activity-wait-loop at the top. In this example, this is the UI-thread, which is called your OnTest handler. The following picture may help:
UI-thread context looks like this...
UI-Thread ->
OnTest
Since you didn't have a connected chain of await/async calls all the way down, you never "attached' the TestRetrieve async context to the above UI-Thread async chain. Effectively, that new context you made is just dangling off in nowhere land. So when you "Wait" the UIThread, it just goes right back to the top.
For async to work, you need to keep a connected async/await chain from the top-level synchronous thread (in this case it's the UI-thread doing this) through all async actions you need to do. You can't make a constructor async, so you can't chain an async context into a constructor. You need to construct the object synchronously and then await TestRetrieve from outside. Remove the 'Wait' line from your constructor and do this...
await (new Cache("test1")).TestRetrieve("test1");
When you do this, the 'TestRetrieve' async context is properly attached, so the chain looks like this:
UI-Thread ->
OnTest ->
TestRetrieve
Now the UI-thread async-loop-handler can properly resume TestRetrieve during async completions and your code will work as expected.
If you want to make an 'async constructor', you need to do something like Drew's GetCacheAsync pattern, where you make a static Async method which constructs the object synchronously and then awaits the async method. This creates the proper async chain by awaiting and 'attaching' the context all the way down.
Related
I have a bunch of async code, I have tried to expand my asyc code as large as possible in my codebase. I am here looking for an safe approach to convert async code to async (wait it finish then return result). I have tied looking on the internet but they either way to complex or may cause deadlocks.
Here is my code:
protected virtual DbData GetDbData()
{
return StorageProvider.RefreshAsync().Result;
}
The GetDbData will be used as a property getter something like:
public override DbData Data
{
get => GetDbData();
set => SetDbData(value);
}
and in constructor
public CachedDataManager(IStorageProvider storageProvider) : base(storageProvider)
{
_cachedData = StorageProvider.RefreshAsync().Result;
}
or for the async method without return value
public CachedDataManager(IStorageProvider storageProvider) : base(storageProvider)
{
DoSomeWorkAsync().GetAwaiter().GetResult();
}
private Task DoSomeWorkAsync()
{
//Assume heavy load.
Task.Delay(5000);
return Task.CompletedTask;
}
Result may causing a deadlock because of the SynchronizationContext when calling in the UI thead (what I know)
All the other solution told me to expand async code as far as possible, I tried, but I can't do it with constructor/property getter
Are there exist some solution similar to Task.Result/Task.Wait/Task.RunSynchronously that does not causes any problems(eg deadlock)?
Also I am not sure about DoSomeWorkAsync().GetAwaiter().GetResult(); it does causes problems with SynchronizationContext or not. I am a noob on this. Please help
A task (what async methods return) can contain every type of logic. Suppose you are calling an async Task method from the Thread A, and you want to synchronously wait for the task to complete. Now let's think carefully what could be the conditions for a deadlock: basically we have to guarantee that the Task do not schedule anything "asynchronously" on the Thread A! If that's the case you can safely call task.GetAwaiter().GetResult(). If not you can't. It's a conceptual limit. There is not a general way to avoid deadlocks.
For example suppose that the Thread A is the UI thread. If the async Task contains a "real" await operation (that is, an await over a Task that is not completed yet, such as Task.Delay(100)), we are already in a bad spot: why? Because the code after the await is wrapped into an Action and scheduled through the Synchronization Context in the UI Thread. So the task is waiting for some code to execute in the UI thread, but the UI thread is waiting for the task to complete
Another example: suppouse the Task method we are awaiting is not async (so contains synchronous code, like Task.Run(VoidMethod)) and that at some point there is a call to Dispatcher.Invoke(). We still have a deadlock: the task to complete should wait for some code to be executed on the UI Thread. But the UI Thread is waiting for that task to complete..
Side note. While in the first example we can do some tricks such as change the Synchronization context temporarily in order to avoid the continuations to run on the UI Thread, in the second example there are no chance to make it work, it's conceptually wrong if you thing about it. So there isn't a general way.
It really depends.
I am pretty sure, this was answered already and I read many related stuff but somehow I am not getting it to work in my code. Here is the exact code base.
I have this async method in my library, that returns a string upon doing some DB entries:
public class MyLibrary
{
public async Task<string> DoSomethingAsync()
{
return await DoAsync();
}
// some private method, with multiple parameters
private Task<string> DoAsync()
{
return Task.Run(() => Do());
}
}
Now on UI, below resulted a frozen state or deadlock:
var myTask = MyLibraryobject.DoSomethingAsync();
console.Write(myTask.Result);
Since my call is awaitable, I think, UI thread waits for my call to finish its business and populate the result, doesn't it? Or since the call is running on another thread, the task might not yet completed when my cursor hits the line 2. So what now? the cursor will wait till the task gets completed or the line 2 gets executed whenever the task gets completed? sounds synchronous to me..
Also if at all, I want to 'exlicitly' wait till the task gets finished, how do i enforce that? some posts, suggested in doing like below, which gave me the result, but created some more confusion:
var myTask = Task.Run(async () => await MyLibraryobject.DoSomethingAsync());
myTask.Wait();
console.Write(myTask.Result);
What is happening above? why should i create another task and set it to wait? can't I wait for the thread, used by the async method? Again, i am clearly missing some basic stuff here.
Lastly, this is an async call, but the UI thread is waiting for it to be completed thus gives me an impression that it's synchronous. Am I thinking it right? Then what is the main purpose of async methods, which return something, and UI waits for it to complete?
Also what's the difference between a fire-and-forget call being non-async and async? is there any benefit of returning Task, instead of void, for such calls?
I am pretty sure, some broken link that connects all these pieces together in my brain. Can someone explain that to me, please??
You should probably start with my async intro and follow up with my article on async best practices. They answer almost all your questions.
For the details...
how and when to fetch return from awaitable(async) method
You should use await to get the result from an async task.
I have this async method in my library, that returns a string upon doing some DB entries
Then it should not be using Task.Run. It should be using naturally-asynchronous APIs, e.g., Entity Framework's FirstAsync.
Since my call is awaitable, I think, UI thread waits for my call to finish its business and populate the result, doesn't it?
No. The UI is blocking because your code is calling Result. Result is a blocking call.
sounds synchronous to me..
That's because you're making it synchronous by using Result. If you use await, the code will execute serially, but asynchronously.
Also if at all, I want to 'exlicitly' wait till the task gets finished, how do i enforce that?
Your code is already doing that. It's explicitly blocking until the task is complete. If you change it to properly use await, it will be explicitly waiting (but not blocking) until the task is complete.
some posts, suggested in doing like below
No. Don't use Task.Run unnecessarily.
can't I wait for the thread, used by the async method?
Pure async methods don't have threads that they use.
Then what is the main purpose of async methods, which return something, and UI waits for it to complete?
Async makes sense when it's consumed with await.
Now on UI, below resulted a frozen state or deadlock:
var myTask = MyLibraryobject.DoSomethingAsync();
This is blocking the UI because it is not awaited. You simply need to await an async method
string res = await MyLibraryobject.DoSomethingAsync();
and the above should be placed in the UI inside an async context too.
Edit - reply to comment do "you mean another wrapper async method, which returns Task<string>..."? No,I don't. When I wrote "inside an async context" I meant to add the async keyword to a subscribed event, like a button click, if you are in the code behind or to your delegate command implementation, if you are in a more advanced MVVM implementation of the GUI.
Furthermore, your class library is supposed to do something truly asynchronous, not just starting a task and wrapping it inside a formally async method, like it is your DoAsync.
Edit - in reply to comment "how should avoid" it? If you can't do async all the way, just keep the library and the API sync and unblock the UI by starting a separate thread to call the sync api.
I have read a lot of articles and still cant get understand this part.
Consider this code :
private async void button1_Click(object sender, EventArgs e)
{
await Dosomething();
}
private async Task<string> Dosomething()
{
await Task.Run((() => "Do Work"));
return "I am done";
}
First question:
When I click the button, it will Call DoSomething and await a Task that creates a Thread from the threadpool by calling Task.Run ( if I am not mistaken ) and all of this runs asynchronously. So I achieved creating a thread that does my work but doing it asynchronously? But consider that I don't need any result back, i just want the work to be done without getting any result back, is there really a need to use async/await , and if so, how?
Second question:
When running a thread asynchronously, how does that work? Is it running on the main UI but on a separate thread or is it running on a separate thread and separate is asynchronously inside that method?
The purpose of creating Async methods is so you can Await them later. Kind of like "I'm going to put this water on to boil, finish prepping the rest of my soup ingredients, and then come back to the pot and wait for the water to finish boiling so I can make dinner." You start the water boiling, which it does asynchronously while you do other things, but eventually you have to stop and wait for it. If what you want is to "fire-and-forget" then Async and Await are not necessary.
Simplest way to do a fire and forget method in C#?
Starting a new task queues that task for execution on a threadpool thread. Threads execute in the context of the process (eg. the executable that runs your application). If this is a web application running under IIS, then that thread is created in the context of the IIS worker process. That thread executes separately from the main execution thread, so it goes off and does its thing regardless of what your main execution thread is doing, and at the same time, your main execution thread moves on with its own work.
1
There's a big difference if you don't await the Task or you await it:
Case you don't await it: DoSomething is called but next sentence is executed while DoSomething Task hasn't been completed.
Case you await it: DoSomething is called and next sentence is executed once DoSomething Task has been completed.
So, the need of async/await will depend on how you want to call DoSomething: if you don't await it is like calling it the fire & forget way.
2
Is it running on the main UI but on a separate thread or is it running
on a seperate thread and separate is asynchronously inside that
method?
Asynchronous code sometimes means other thread (see this Q&A Asynchronous vs Multithreading - Is there a difference?). That is, either if the code is being executed in a separate thread from the UI one or it lets continue the processing of the UI thread while it gets resumed, it's nice because UI loop can still update the screen while other tasks are being done in parallel without freezing the UI.
An asynchronous method (i.e. async method) is a syntactic sugar to tell the compiler that await statements should be treated as a state machine. The C# compiler turns your async/await code into a state machine where code awaiting a Task result is executed after the code that's being awaited.
Interesting Q&As
You might want to review these other Q&As:
Async/Await vs Threads
What's the difference between Task.Start/Wait and Async/Await?
async/await - when to return a Task vs void?
Is Async await keyword equivalent to a ContinueWith lambda?
OP said...
[...] But does this mean that "async/await" will fire off a thread and
Task.Run also fires off a thread or are they both the same thread?
Using async-await doesn't mean "I create a thread". It's just a syntactic sugar to implement continuations in an elegant way. A Task may or may not be a thread. For example, Task.FromResult(true) creates a fake task to be able to implement an async method without requirement it to create a thread:
public Task<bool> SomeAsync()
{
// This way, this method either decides if its code is asynchronous or
// synchronous, but the caller can await it anyway!
return Task.FromResult(true);
}
The type Task<TResult> requires you to return a TResult from your task. If you don't have anything to return, you can use Task instead (which, incidentally, is the base class of Task<TResult>).
But keep in mind that a task is not a thread. A task is a job to be done, while a thread is a worker. As your program runs, jobs and workers become available and unavailable. Behind the scenes, the library will assign your jobs to available workers and, because creating new workers is a costly operation, it will typically prefer to reuse the existing ones, through a thread pool.
I'm creating my own UI handling logic that runs on a single thread. Basically, what I'm doing is
void HandlerMain()
{
while (true)
{
Task[] events = PumpEvents();
Task.WaitAll(events);
}
}
where one example task that PumpEvents() returns is
async Task ButtonClick()
{
var httpClient = new HttpClient();
string s = await httpClient.GetStringAsync("http://microsoft.com");
Console.WriteLine(s);
}
The problem of my code is, if one of events takes a long time, it's stuck at Task.WaitAll(), so it can't pump new events making the UI not responsive. Is there any other method than WaitAll() something like
Task[] remainingEvents = PumpEvents();
while (true)
{
remainingEvents = WaitUntilEveryTasksAwait(remainingEvents);
remainingEvents.Append(PumpEvents());
}
Maybe I'm on wrong track. I'd appreciate your advice!
#ScottChamberlain No. The built-in UI processor, say WPF, correctly handles async events so whenever the async events do "await", it skips the current context and handles the next events. I want to duplicate this behavior
Based on your comment to me I now understand what your problem is. You need more logic than your simple while(true) loop to be able to process the await messages. The entire system is built up upon the class SynchronizationContext, what you will need to do is derive your own class from SynchronizationContext and override it's methods to queue up your work to be done inside your while loop.
See this article from Stephen Cleary to give you more information on how a Synchronization Context works and posibly some ideas on where to start writing your own.
If I'm understanding, you don't actually need to wait until those tasks are complete to continue. Just remove the call to Task.WaitAll.
For the record, Task.WaitAll is synchronous -- it blocks. You're better off using Task.WhenAll, which returns a task that completes when all of the provided tasks are complete. That lets you await it just like you'd await any of the individual tasks. Just doing that would solve the problem and keep the UI responsive.
E.g.:
async Task HandlerMain()
{
while (true)
{
Task[] events = PumpEvents();
await Task.WhenAll(events);
}
}
Of course, in this case, depending on what was calling HandlerMain, you'd still have the problem where PumpEvents was hung up waiting on the long-running task.
This starts to lead down the path of questions like, "Why are you writing your own custom UI message pump when WPF and WinForms have that problem already solved?"
I'm evaluating the Async CTP.
How can I begin execution of an async function on another thread pool's thread?
static async Task Test()
{
// Do something, await something
}
static void Main( string[] args )
{
// Is there more elegant way to write the line below?
var t = TaskEx.Run( () => Test().Wait() );
// Doing much more in this same thread
t.Wait(); // Waiting for much more then just this single task, this is just an example
}
I'm new (my virginal post) to Stack Overflow, but I'm jazzed that you're asking about the Async CTP since I'm on the team working on it at Microsoft :)
I think I understand what you're aiming for, and there's a couple of things you're doing correctly, to get you there.
What I think you want:
static async Task Test()
{
// Do something, await something
}
static void Main(string[] args)
{
// In the CTP, use Task.RunEx(...) to run an Async Method or Async Lambda
// on the .NET thread pool
var t = TaskEx.RunEx(Test);
// the above was just shorthand for
var t = TaskEx.RunEx(new Func<Task>(Test));
// because the C# auto-wraps methods into delegates for you.
// Doing much more in this same thread
t.Wait(); // Waiting for much more then just this single task, this is just an example
}
Task.Run vs. Task.RunEx
Because this CTP installs on top of .NET 4.0, we didn't want to patch the actual System.Threading.Tasks.Task type in mscorlib. Instead, the playground APIs are named FooEx when they conflicted.
Why did we name some of them Run(...) and some of the RunEx(...)? The reason is because of redesigns in method overloading that we hadn't completed yet by the time we released the CTP. In our current working codebase, we've actually had to tweak the C# method overloading rules slightly so that the right thing happens for Async Lambdas - which can return void, Task, or Task<T>.
The issue is that when async method or lambdas return Task or Task<T>, they actually don't have the outer task type in the return expression, because the task is generated for you automatically as part of the method or lambda's invocation. This strongly seems to us like the right experience for code clarity, though that does make things quite different before, since typically the expression of return statements is directly convertible to the return type of the method or lambda.
So thus, both async void lambdas and async Task lambdas support return; without arguments. Hence the need for a clarification in method overload resolution to decide which one to pick. Thus the only reason why you have both Run(...) and RunEx(...) was so that we would make sure to have higher quality support for the other parts of the Async CTP, by the time PDC 2010 hit.
How to think about async methods/lambdas
I'm not sure if this is a point of confusion, but I thought I'd mention it - when you are writing an async method or async lambda, it can take on certain characteristics of whoever is invoking it. This is predicated on two things:
The type on which you are awaiting
And possibly the synchronization context (depending on above)
The CTP design for await and our current internal design are both very pattern-based so that API providers can help flesh out a vibrant set of things that you can 'await' on. This can vary based on the type on which you're awaiting, and the common type for that is Task.
Task's await implementation is very reasonable, and defers to the current thread's SynchronizationContext to decide how to defer work. In the case that you're already in a WinForms or WPF message loop, then your deferred execution will come back on the same message loop (as if you used BeginInvoke() the "rest of your method"). If you await a Task and you're already on the .NET threadpool, then the "rest of your method" will resume on one of the threadpool threads (but not necessarily the same one exactly), since they were pooled to begin with and most likely you're happy to go with the first available pool thread.
Caution about using Wait() methods
In your sample you used:
var t = TaskEx.Run( () => Test().Wait() );
What that does is:
In the surrounding thread synchronously call TaskEx.Run(...) to execute a lambda on the thread pool.
A thread pool thread is designated for the lambda, and it invokes your async method.
The async method Test() is invoked from the lambda. Because the lambda was executing on the thread pool, any continuations inside Test() can run on any thread in the thread pool.
The lambda doesn't actually vacate that thread's stack because it had no awaits in it. The TPL's behavior in this case depends on if Test() actually finished before the Wait() call. However, in this case, there's a real possibility that you will be blocking a thread pool thread while it waits for Test() to finish executing on a different thread.
That's the primary benefit of the 'await' operator is that it allows you to add code that executes later - but without blocking the original thread. In the thread pool case, you can achieve better thread utilization.
Let me know if you have other questions about the Async CTP for VB or C#, I'd love to hear them :)
It's usually up to the method returning the Task to determine where it runs, if it's starting genuinely new work instead of just piggy-backing on something else.
In this case it doesn't look like you really want the Test() method to be async - at least, you're not using the fact that it's asynchronous. You're just starting stuff in a different thread... the Test() method could be entirely synchronous, and you could just use:
Task task = TaskEx.Run(Test);
// Do stuff
t.Wait();
That doesn't require any of the async CTP goodness.
There would be, if this wasn't a console application. For example, if you do this in a Windows Forms application, you could do:
// Added to a button click event, for example
public async void button1_Click(object sender, EventArgs e)
{
// Do some stuff
await Test();
// Do some more stuff
}
However, there is no default SynchronizationContext in a console, so that won't work the way you'd expect. In a console application, you need to explicitly grab the task and then wait at the end.
If you're doing this in a UI thread in Windows Forms, WPF, or even a WCF service, there will be a valid SynchronizationContext that will be used to marshal back the results properly. In a console application, however, when control is "returned" at the await call, the program continues, and just exits immediately. This tends to mess up everything, and produce unexpected behavior.