Consider the following:
public async Task<bool> DoSomethingAsync()
{
// no creation of a task in these statements
statement2;
statement3;
statement4;
return Task.FromResult( true );
}
public async Task MyMethod()
{
statement1;
await DoSomethingAsync().ConfigureAwait( false );
statement5;
}
Is there any asynchronous behaviour to be run when awaiting DoSomethingAsync?
Is there any asynchronous behaviour to be run when awaiting DoSomethingAsync?
No, there isn't. When DoSomthingAsync is called, it is executed whole and returned Task is already finished. So when await tries to wire-up the callback logic, it finds out the task is already finished and just continues execution without bothering with the callback logic.
But all of those are implementation details and it is possible those details will change. You should not build your code with the assumption this code will run synchronously. Any addition of await inside DoSomthingAsync will make the code completely asynchronous without you noticing.
Also, DoSomthingAsync the way it is right now does not compile. You either remove the async, in which case it is clear that DoSomthingAsync is not asynchronous. Or you just have return true; , in which case the compiler should warn you that method does not contain any await and will complete synchronously.
Considering your question in comment:
public async Task<bool> DoSomethingAsync()
{
statement2;
await statement3; // << Diverges here
statement4;
return true;
}
// all code below this line is completely irrelevant
// to whenever or where the code above diverges
public async Task MyMethod()
{
statement1;
await DoSomethingAsync().ConfigureAwait( false );
statement5;
}
Related
I have a decent understanding of how Async/Await works in C#.
I understand that when the await keyword is reached, control is given back to the calling function and that is how asynchronous execution is achieved (if I am wrong here, I would appreciate correction and a better explanation).
However I am not sure as to how I would make sure that an async function has finished executing before returning from a function.
Take the example below:
private static async Task<bool> LoadDataIntoLocalAppFile(ZipArchiveEntry entry, string key)
{
try
{
/* SqLiteAsyncConnection is an instance variable in the class that has this function.*/
string pathToUse = "localDatabase.db"
if (SqLiteAsyncConnection != null)
{
await SqLiteAsyncConnection.CloseAsync()
.ContinueWith(x => entry.ExtractToFile(pathToUse, true));
}
else
{
entry.ExtractToFile(pathToUse, true);
}
return true;
}
catch (Exception ex)
{
Colsole.WriteLine(ex.ToString());
return false;
}
}
In the above code snippet, I want to make sure that my SqLiteAsyncConnection is closed before I replace the data in the .db file with the contents of entry (so that it does not error out). As such I have used ContinueWith (if this is wrong I would appreciate some clarification).
But I also want to ensure that await SqLiteAsyncConnection.CloseAsync().ContinueWith(x => entry.ExtractToFile(pathToUse, true)); finishes its execution before the function returns. That is I want to ensure that this function does not return true inaccurately, and that it does not return true before await SqLiteAsyncConnection.CloseAsync() .ContinueWith(x => entry.ExtractToFile(pathToUse, true)); finishes its execution.
How do I achieve this?
You don't need the ContinueWith when you have await there. You would use ContinueWith if you don't use await, it can be seen as a type of callback once the parent task has completed/failed.
await SqLiteAsyncConnection.CloseAsync()
.ContinueWith(x => entry.ExtractToFile(pathToUse, true));
//can be replaced by
await SqLiteAsyncConnection.CloseAsync();
entry.ExtractToFile(pathToUse, true);
When you hit an await section in your code, your function isn't done, it doesn't return true, it gets suspended in a sense and the control is given back to calling thread. Once all your awaits have completed in the function, only then does it return the result.
When the await keyword is reached, control is given back to the calling function.
I find this commonly used explanation confusing. In simpler terms, the job of an asynchronous method is to create a Task. That's why you call the method, to get a Task back. You get this Task when the first¹ await is reached inside this method. At this point the asynchronous operation has started, and (generally) it has not completed yet. The caller has received the Task that represents the asynchronous operation, and can continue doing other things while the operation is in-flight. In some cases the caller has nothing better to do than wait for the completion of the asynchronous operation, in which case you see this pattern:
await LoadDataIntoLocalAppFile();
Here the caller is itself an asynchronous method. We know it because of the await keyword. The code above is equivalent with this:
Task task = LoadDataIntoLocalAppFile();
await task;
The first line will complete when the first await inside the LoadDataIntoLocalAppFile is reached. The second line will complete when the last line of code inside the LoadDataIntoLocalAppFile has ran.
¹ To be more precise, the first await of a non-completed awaitable.
Your understanding of async/await is incorrect, just awaiting the asynchronous call is enough:
private static async Task<bool> LoadDataIntoLocalAppFile(ZipArchiveEntry entry, string key)
{
try
{
string pathToUse = "localDatabase.db"
await SqLiteAsyncConnection?.CloseAsync();
entry.ExtractToFile(pathToUse, true);
return true;
}
catch (Exception ex)
{
Colsole.WriteLine(ex.ToString());
return false;
}
}
Then call with:
await LoadDataIntoLocalAppFile(...
I have the following code (https://github.com/avinash0161/OrleansExperiments/tree/c0155b4b0c8c1bfe60aea8624f2cc83a52853dc7):
// Client code
Console.WriteLine("Client making a call");
var hashGenerator = client.GetGrain<IGrainA>(0);
hashGenerator.Call_A_ToTemp();
await Task.Delay(1000);
hashGenerator.Call_B_ToTemp();
// GrainA code
public async Task Call_A_ToTemp()
{
Console.WriteLine("Making call A to a fellow grain");
IGrainB grain = this.GrainFactory.GetGrain<IGrainB>(1);
grain.CallA().ContinueWith((t)=>
{
if(t.IsFaulted)
{
// Silo message timeout is 32s so t.IsFaulted is true
Console.WriteLine("Task Faulted");
Call_A_ToTemp();
}
});
}
public async Task Call_B_ToTemp()
{
Console.WriteLine("Making call B to a fellow grain");
IGrainB grain = this.GrainFactory.GetGrain<IGrainB>(1);
await grain.CallB();
}
// GrainB code
public async Task CallA()
{
Console.WriteLine("Call A came to GrainB");
await Task.Delay(34000); // more than timeout for the caller
}
public Task CallB()
{
Console.WriteLine("Call B came to GrainB");
return Task.CompletedTask;
}
The output for this code is:
Client making a call
Making call A to a fellow grain
Call A came to GrainB
Making call B to a fellow grain
Task Faulted <---------------- This comes after Call_B_ToTemp executes
Making call A to a fellow grain
As we can see, that Call_B_ToTemp executes before Call_A_ToTemp executes completely (ContinueWith part of Call_A_ToTemp is executed later). Is this expected and does it violate the single threaded nature of the grains?
When I replaced the code in Call_A_ToTemp() with:
public async Task Call_A_ToTemp()
{
Console.WriteLine("Making call A to a fellow grain");
IGrainB grain = this.GrainFactory.GetGrain<IGrainB>(1);
bool isSuccess = false;
while (! isSuccess)
{
try
{
await grain.CallA();
isSuccess = true;
} catch(TimeoutException){
Console.WriteLine("task faulted");
}
}
}
The code now preserves the single threaded nature and Call_B_ToTemp isn't called till all of ContinueWith part of Call_A_ToTemp() is executed. The console output is like:
Client making a call
Making call A to a fellow grain
Call A came to GrainB
Task Faulted
Making call A to a fellow grain
Can anyone please explain this? Is the single threaded nature violated when there is ContinueWith?
The single-threaded nature is not being violated. The compilation warnings in your project makes the source of the issue clear. In particular: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
The method async Task Call_A_ToTemp() never awaits the call to grain B. Instead, it returns immediately after issuing the call. Because the Task returned by Call_A_ToTemp() is immediately completed, another call is allowed to execute on the grain. Once grain.CallA() completes, the continuation (ContinueWith(...)) will execute on the grain's TaskScheduler as soon as possible (eg, while the grain is awaiting another call or sitting idle).
Instead, if the call was awaited or if async was removed from the method and the code changed to return the grain.CallA().ContinueWith(...) call then the expected behavior will be observed. I.e, changing the code to this will give you the expected result:
// removed 'async' here, since we're not awaiting anything.
// using 'async' is preferred, but this is to demonstrate a point about
// using ContinueWith and un-awaited calls
public Task Call_A_ToTemp()
{
Console.WriteLine("Making call A to a fellow grain");
IGrainB grain = this.GrainFactory.GetGrain<IGrainB>(1);
// Note the 'return' here
return grain.CallA().ContinueWith((t)=>
{
if(t.IsFaulted)
{
// Silo message timeout is 32s so t.IsFaulted is true
Console.WriteLine("Task Faulted");
Call_A_ToTemp();
}
});
}
In my WPF application, i am calling relaycommand
private void AutoRun(object parameter)
{
for(int i=0;i<10;i++)
{
MoveLotCommand.Execute(0);
}
}
which inturns call another relay command
private void MoveLot(object parameter)
{
//Some Code
var Task = StartLotProcessing(currentAssemblyPlant);
}
}
and this relay command will call another async function
async Task StartLotProcessing(int currentAssemblyPlant)
{
await Task.Delay(5000);
var nextAssemblyPlant = currentAssemblyPlant + 1;
//Process after await
}
The issue is, my code after 'await Task.Delay(5000)' does not executes until my AutoRun() function execution is completed.
I am trying to execute the await async code for each variable in my for loop.
Any help would be appreciated and sorry for my explanation.
You are not calling the method correctly : you are missing the await operator to indicate that you have to wait, otherwise you effectively schedule the task but do not wait for it. The task is scheduled in a synchronous fashion, hence when your method returns.
Change your call to this, and the issue should go away:
await StartLotProcessing(currentAssemblyPlant);
The problem appears to be that you are calling StartLotProcessing asynchronously but not waiting for the task to complete before moving on.
Ideally you would call use async/await the whole way up the stack:
await MoveLotCommand.Execute(0);
...
await StartLotProcessing(currentAssemblyPlant);
If you're unable to do that, then you should call
var task = StartLotProcessing(currentAssemblyPlant);
...
task.Wait();
I can't understand if await statement is required when async method call is the last call in my async method. E.g.
public async Task CallAsync(byte[] data)
{
await Call1Async(data);
Call2Async(data);
}
public async Task Call1Async(byte[] data)
{
...
}
public async Task Call2Async(byte[] data)
{
...
}
The above would compile but with a warning "consider applying await to this method". But I think it would be waste of resources to apply await for the last call in the method.
At the same time, if I use return Call2Async(data); instead of just Call2Async(data);, the warning would go away. This indicates await is not actually required in such situation.
But this only works for methods which have a return value (i.e. Task<T> rather than just Task). I need this for methods without return values. Is there any way to do the same for value-returning methods?
I.e. I need to somehow return Task object returned by Call2Async to the caller of CallAsync and I can't use return statement in CallAsync explicitly as my methods don't have return values. Of course, I can adjust them all to return values (e.g. true) but it would not be an elegant solution.
P.S. If I have the only async call in my method, I just don't add 'async' to the method signature, and it works ('return' statement not required). But if the method contains more than one async call, I need to have 'async' modifier to be able to await for the first call 'await Call1Async(data)'. And adding 'async' modifier makes the compiler require 'return' to return Task object to the caller (and this works only for methods with return values). That's what I'm trying to overcome.
In the following method:
public async Task CallAsync(byte[] data)
{
await Call1Async(data);
Call2Async(data);
}
Control from the method returns after beginning Call2Async. That is, if you were to await CallAsync(data), it would finish before Call2Async ends. This is probably not what you intended. This method will only finish when both calls are complete:
public async Task CallAsync(byte[] data)
{
await Call1Async(data);
await Call2Async(data);
}
You can see the difference in these example outputs (I implemented the two async calls to simply print a start, delay for a second, and then print an end).
void Main()
{
Console.WriteLine("Main start");
CallAsync(null).Wait();
Console.WriteLine("Main end");
}
The method without the second await prints:
Main start
Call1Async start
Call1Async end
Call2Async start
Main end
Call2Async end
And with the second await:
Main start
Call1Async start
Call1Async end
Call2Async start
Call2Async end
Main end
This implementation also has a problem:
public Task CallAsync(byte[] data)
{
Call1Async(data);
return Call2Async(data);
}
It kicks off both async calls at the same time, but then returns control when Call2Async completes, whether Call1Async is complete or not. Again, this is probably not what you intended.
async keyword indicates that the method is asynchronous and than it will contain the await keyword in it.
I don't understand why you have multiple asynchronous methods?
Consider the following example :
async void MyMethod()
{
Task<object> result = MyWorkAsync();
MyIndependentOtherWork();
object res = await result;
}
Calling MyWorkAsync is like creating a thread "toto" to execute the method (i.e Thread.Start(MyWorkAsyn))
The await keyword is like making a join form the current thread to the thread "toto" and than getting the result of "toto", and in the mean time you get your other independent work to execute on the current thread
i go through a msdn sample code where a function is called when button is clicked and when routine is called then Await keyword is used and function has async keyword used.
private async void StartButton_Click(object sender, RoutedEventArgs e)
{
int contentLength = await AccessTheWebAsync();
resultsTextBox.Text +=
String.Format("\r\nLength of the downloaded string: {0}.\r\n", contentLength);
}
async Task<int> AccessTheWebAsync()
{
HttpClient client = new HttpClient();
Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");
DoIndependentWork();
string urlContents = await getStringTask;
return urlContents.Length;
}
void DoIndependentWork()
{
resultsTextBox.Text += "Working . . . . . . .\r\n";
}
When AccessTheWebAsync is called then await keyword is used, what does it mean?
When this function AccessTheWebAsync() will be executing then DoIndependentWork() function is called and i guess here control will be waiting until this function DoIndependentWork() is finished. Am I right?
again there is another statement called
string urlContents = await getStringTask;
why they use here await. if we do not use await here then what would happen?
Please guide me to understand the code that how it is working.
I have an intro blog post here, and the MSDN docs are also extremely good.
You can think of await as "pausing" the method (without blocking the thread) until the awaitable operation completes. When this happens, it returns a task that is not completed to the calling method, so it also has the option to await.
Here's a brief description about async/await methods.
Async Methods:
Caller is not necessarily blocked for the full execution of async
method
Possible return types
void: “fire-and-forget”
Task: allows to await termination of async method
Task<T>: allows to await termination and get result of type T
No ref or out parameter for async methods
Must again contain an await => Otherwise compile warning
await for Tasks
Await termination of a TPL task
Return result of task (if task with
result type)
Must only occur in async methods => Otherwise compile error
An async method is partly synchronous and partly asynchronous
Caller synchronously executes the method until a blocking await
Thereafter, the method rest is asynchronously executed
async & await Mechanism
Efficient
public async Task<int> GetSiteLengthAsync(string url)
{
HttpClient client = new HttpClient(); <= Sync
Task<string> download1 = client.GetStringAsync(url); <= Sync
string site1 = await download1; <= Async (Another thread)
return site1.Length; <= Async (Another thread)
}
Not sure if that simplier for you to understand that in the following way, but this is how it helped myself:
As you can see, the AccessTheWebAsync returns Task<int> but not just int.
If you would have called it without "await", you would just get the Task<int> object as its result. And could do anything further you want (manually) with that task: for instance, to wait until it finishes theTask.Wait(); and obtain the result of int in theTask.Result.
But await does all that instead of you and returns just int: Task<int> => int.
This is it.
from MSDN:
the await operator is applied to a task in an asynchronous method to suspend the execution of the method until the awaited task completes. The task represents ongoing work.await does not block the thread on which it is executing. Instead, it causes the compiler to sign up the rest of the async method as a continuation on the awaited task. Control then returns to the caller of the async method. When the task completes, it invokes its continuation, and execution of the async method resumes where it left off.
So when the compiler encounter
int contentLength = await AccessTheWebAsync();
it waits till the AccessTheWebAsync() task is complted
please take a look at this example C# Async,Await
All await does is blocks the thread until the result of an async operation returns.
Edit: sorry when I said block I should have said suspend, since blocking would prevent execution from continuing!
Edit2: As Alex pointed out - I should have probably said "execution is suspended" rather than the thread. Basically "Stuff happens until await returns but the point is it appears you are writing and executing synchronous code"
Since async operations have the potential to be take a while (e.g. web service calls), they tend to use callbacks to return a result.
If you have to handle callbacks in your code it can get a little messy, especially when waiting on multiple async tasks that are dependant on each other. Async/await and Task simplify the code so that you can write async code literally in the order you would read it.
e.g. example standard async code with callbacks:
public int CallSomeServiceAndReturnItsValue()
{
int result = 0;
WebService.SomeAsyncServiceCall((svcResult) => { result = svcResult.Value; });
return result;
}
and if you have multiple calls that need to be chained:
public int CallSomeServiceAndReturnItsValue()
{
int result = 0;
WebService.GetSomeIdentifier((svcResult) =>
{
var identifier = svcResult.Value;
WebService.GetResult(identifier, (anotherResult) =>
{
result = anotherResult.Value;
}
}
);
return result;
}
As you can see, it starts getting messy, the code doesn't really read in an order that feels natural. The alternative is to use callback methods instead of anonymous methods but still, the callback methods are far away from the code that called them and things can feel disjointed
The other alternative is of course async/await which is much clearer
public int CallSomeServiceAndReturnItsValue()
{
int identifier = await WebService.GetSomeIdentifier();
return await WebService.GetResult(identifier);
}