Cleanest way of dealing with an IAsyncOperationWithProgress? - c#

I've been using C# for quite a while, but somehow have not yet had the pleasure of using the whole await/async thing new in .Net 4. Well, now I'm making a console application that links to the WinRT libraries and WinRT is really.. well, asynchronous.
One thing I'm needing to do right now is install a package. So, I use PackageManager.AddPackageAsync This is of course asynchonous and returns an IAsyncOperationWithProgress
I know I could do something like
bool Done=false;
void Foo()
{
var tmp=new PackageManager.AddPackageAsync(...);
tmp.Completed= ... FooBar;
while(!Done){}
}
void FooBar(...)
{
Done=true;
}
But I'm pretty sure the whole async and await thing was designed for exactly this scenario. However, I don't understand how to use it in this context on an IAsyncOperationWithProgress

.Net includes a GetAwaiter() extension method that makes IAsyncOperationWithProgress awaitable.
You can just write await tmp; in an async method.
Your async method will return a Task (or Task<T>), which you can await from another async method, or call Wait() to synchronously block.

Async and Await allows you to program an Async operation as if it occurs on the calling thread. First you have to declare your operation as being async then you await the async operation from the other guy. Finally you do whatever work you wanted to do after that operation is complete.
async void Foo()
{
var tmp=await new PackageManager().AddPackageAsync(...);
//do something else;
}
Calling Foo will make it run in the background, but when AddPackageAsync completes, Foo rejoins the calling thread (e.g. the UI thread) to complete its work.
The other option is to call GetAwaiter extension method and call Wait() on it to manually block until the operation completes.

You can subscribe to that progress by using an overload of AsTask method, like the following
...= await new PackageManager().AddPackageAsync(...).AsTask(new Progress<DeploymentProgress>(...));

Related

Sync calling async nested methods - Will async work down the path?

I have async methods inside my libraries and the top level call is made at the handler of AWS Lambda functions synchronously (for some reason not to discuss here). I wonder if any calls made down the track be asynchronous by any chance? or because the first caller does it synchronously will everything be synchronous?
public void LambdaHandler(Input inp, ILambdaContext context)
{
method1().GetAwaiter().GetResult();
}
private async Task method1()
{
await method2();
await method3();
}
private async Task method2()
{
//do something
}
private async Task method3()
{
//do something
}
method2 and method3 will do whatever they always have done. If they are purely synchronous behind a Task API, then they will continue to be synchronous; if they are asynchronous, then they will continue to be asynchronous. The only question here is: what will LambdaHandler do, and the answer to that is simply:
it will block until they are complete
If they are already complete synchronously, then fine; if they aren't, then you've tied up a thread in a sync-over-async block. This could by itself cause a deadlock if your code uses a sync-context or task-scheduler that only has a single worker (which isn't uncommon), as the thread that the async code will need to do any post-processing will be stuck waiting at GetResult(). So the async part can't complete, and GetResult() can't complete.
You should avoid sync-over-async like the plague. There is a reason it is considered an anti-pattern.
The methods down below the call stack will run asynchronously.
But the entire thing would block and wait for the task to complete.
The better way is to modify LambdaHandler to return Task and use await instead of calling the GetAwaiter.
Help link

how and when to fetch return from awaitable(async) method

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.

C# spawn new task

Suppose I have this function:
void DoWork()
{
//do long work
}
I want this function to be executed on a different thread.
I'm used to use threads, so one way to execute it on a thread is:
new Thread(DoWork).Start();
I'm trying to learn the new task/await C# feature so I modified the method to
async Task DoWork()
{
await Task.Run(delegate() { /*do stuff*/});
}
Now I can use it this way:
DoWork().Wait(0);
Or I can modify the method again to:
async void DoWork()
{
await Task.Run(delegate() { /*do stuff*/});
}
And now just call:
DoWork();
Which solution should I use ?
I do not need the result of the task nor waiting for it to finish.
The answer is neither. You are creating a trivial asynchronous wrapper around synchronous logic.
Stephen Cleary: using Task.Run for asynchronous wrappers is a code smell
Stephen Toub (Microsoft): Should I expose asynchronous wrappers for synchronous methods? (and no, you shouldn't).
The async part of your DoWork method adds no value. It diminishes the value of your API by making it impossible to execute your potentially complex "do stuff" logic in any way other than fire-and-forget.
The correct approach is to ditch Task.Run and strip your method down to the bare essentials:
void DoWork()
{
// Do long CPU-bound work, synchronously
}
...
// Then, somewhere in the calling code:
Task.Run(() => DoWork()); // Fire and forget unless you await the resulting Task or block on it.
Task.Run is currently the preferred method of scheduling work on the thread pool (as of .NET 4.6.x)

Difference between calling an async method and Task.Run an async method

I have a method in my view model
private async void SyncData(SyncMessage syncMessage)
{
if (syncMessage.State == SyncState.SyncContacts)
{
this.SyncContacts();
}
}
private async Task SyncContacts()
{
foreach(var contact in this.AllContacts)
{
// do synchronous data analysis
}
// ...
// AddContacts is an async method
CloudInstance.AddContacts(contactsToUpload);
}
When I call SyncData from the UI commands and I'm syncing a large chunk of data UI freezes. But when I call SyncContacts with this approach
private void SyncData(SyncMessage syncMessage)
{
if (syncMessage.State == SyncState.SyncContacts)
{
Task.Run(() => this.SyncContacts());
}
}
Everything is fine. Should not they be the same?
I was thinking that not using await for calling an async method creates a new thread.
Should not they be the same? I was thinking that not using await for
calling an async method creates a new thread.
No, async does not magically allocate a new thread for it's method invocation. async-await is mainly about taking advantage of naturally asynchronous APIs, such as a network call to a database or a remote web-service.
When you use Task.Run, you explicitly use a thread-pool thread to execute your delegate. If you mark a method with the async keyword, but don't await anything internally, it will execute synchronously.
I'm not sure what your SyncContacts() method actually does (since you haven't provided it's implementation), but marking it async by itself will gain you nothing.
Edit:
Now that you've added the implementation, i see two things:
I'm not sure how CPU intensive is your synchronous data analysis, but it may be enough for the UI to get unresponsive.
You're not awaiting your asynchronous operation. It needs to look like this:
private async Task SyncDataAsync(SyncMessage syncMessage)
{
if (syncMessage.State == SyncState.SyncContacts)
{
await this.SyncContactsAsync();
}
}
private Task SyncContactsAsync()
{
foreach(var contact in this.AllContacts)
{
// do synchronous data analysis
}
// ...
// AddContacts is an async method
return CloudInstance.AddContactsAsync(contactsToUpload);
}
What your line Task.Run(() => this.SyncContacts()); really does is creating a new task starting it and returning it to the caller (which is not used for any further purposes in your case). That's the reason why it will do its work in the background and the UI will keep working. If you need to (a)wait for the task to complete, you could use await Task.Run(() => this.SyncContacts());. If you just want to ensure that SyncContacts has finished when you return your SyncData method, you could using the returning task and awaiting it at the end of your SyncData method. As it has been suggested in the comments: If you're not interested in whether the task has finished or not you just can return it.
However, Microsoft recommend to don't mix blocking code and async code and that async methods end with Async (https://msdn.microsoft.com/en-us/magazine/jj991977.aspx). Therefore, you should consider renaming your methods and don't mark methods with async, when you don't use the await keyword.
Just to clarify why the UI freezes - the work done in the tight foreach loop is likely CPU-bound and will block the original caller's thread until the loop completes.
So, irrespective of whether the Task returned from SyncContacts is awaited or not, the CPU bound work prior to calling AddContactsAsync will still occur synchronously on, and block, the caller's thread.
private Task SyncContacts()
{
foreach(var contact in this.AllContacts)
{
// ** CPU intensive work here.
}
// Will return immediately with a Task which will complete asynchronously
return CloudInstance.AddContactsAsync(contactsToUpload);
}
(Re : No why async / return await on SyncContacts- see Yuval's point - making the method async and awaiting the result would have been wasteful in this instance)
For a WPF project, it should be OK to use Task.Run to do the CPU bound work off the calling thread (but not so for MVC or WebAPI Asp.Net projects).
Also, assuming the contactsToUpload mapping work is thread-safe, and that your app has full usage of the user's resources, you could also consider parallelizing the mapping to reduce overall execution time:
var contactsToUpload = this.AllContacts
.AsParallel()
.Select(contact => MapToUploadContact(contact));
// or simpler, .Select(MapToUploadContact);

Proper approach on async/await method including Lambda

I would like to show two paradigms about async programming and listen to your comments.
A.
Let's say you have created a method like the following in a library to use it from your GUI clients.
public async Task<TestObject> DoSomeWork(string aParam1, object aParam2)
{
TestObject testObj = new TestObject();
...fill in params to testObj...
await MethodCallAsync(testObj);
....do other work synchronous.....
....continue fill testObj properties...
await Task.Delay(1000) // just a delay for no reason
...continue synchronous work.....
return testObj;
}
Ok, but this will chop my GUI context into small calling pieces, right? or I don't know if from the moment you declare a method async it will create a Task for all the operations inside?
If yes then great, no problem we can just declare it async and move on with our lives.
Lets say no and I would like to take the following approach so I won't disturb the GUI at all until my whole method call finishes and take the result so do something in my calling method.
B.
Another approach would be.
public async Task<TestObject> DoSomeWork(string aParam1, object aParam2)
{
TestObject testObj = new TestObject()
..fill state params....
return await Task.Factory.StartNew((state) =>
{
//But now I need to do async/await in here
// is it a good practice to async await lambdas?
// async/await practices say it's ok as long sas it is not becoming async void
// which in our case is not.
await MethodCallAsync(testObj);
....do other work synchronous.....
....continue fill state properties...
await Task.Delay(1000) // just a delay for no reason
...continue synchronous work.....
return state; // Our state and TestObject to examine after completion
}, testObj);
}
Our problem now it's not only if we should asyncify the lambda, say you do it, it the will return a Task<Task<TestObject>> and definitely we don't want that.
You should call this up in the pipeline, most probably your GUI class.
private async void SomethingClickedOrTouched(object sender, EventArgs e)
{
await RunThisAsyncToDoYourJob();
}
private async Task RunThisAsyncToDoYourJob()
{
TestObject testObj = await myObject.DoSomeWork("param1", anotherObject);
}
It just bugs me a little and I really want into detail with async programming.
So, is A paradigm the correct approach anyway, and use the B paradigm only when the Task lambda inside code is completely synchronous?
Thank you in advance.
Regards.
The proper way to write an async method is to use ConfigureAwait(continueOnCapturedContext: false) whenever you don't need to resume on the captured context. This is normally done for all "library" code.
this will chop my GUI context into small calling pieces, right?
Yes (since you're not using ConfigureAwait).
or I don't know if from the moment you declare a method async it will create a Task for all the operations inside?
Yes, async will create a Task that represents the async method. However, the fact that there is a Task does not mean that its code is running on a background thread.
it the will return a Task<Task<TestObject>> and definitely we don't want that.
I'd like to know where everyone is getting the idea of using Task.Factory.StartNew for asynchronous tasks. Task.Run is superior if you want to run code on a background thread.
I have an async intro on my blog that you may find helpful.

Categories

Resources