How to sequential multilevel async process with C#? - c#

I have a daily scheduler sequential scenario that needs to run every midnight:
Check_Tenant_Expiry and Get its return value (true/false)
Run_Daily_Report (pass the returning value from Check_Tenant_Expiry)
I expect to do Check_Tenant_Expiry and after it completed it will continue with Run_Daily_Report, I use the code below
bool _xxx = await Check_Tenant_Expiry().ContinueWith(t =>
{
Run_Daily_Report(_xxx); // THE WARNING GOES HERE
}, TaskContinuationOptions.OnlyOnRanToCompletion);
public static async Task<bool> Check_Tenant_Expiry()
{
bool _ret = false;
...
...
return await Task.FromResult(_ret);
}
public static async Task Run_Daily_Report()
{ .... }
questions:
Why I got a warning on Run_Daily_Report:
Severity Code Description Project File Line Suppression State
Warning CS4014 Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
I am not sure that I already have correct logic for the sequential multilevel process like first I need to run Check_Tenant_Expiry() until it finished completely and then continue with Run_Daily_Report()
I need advice.
Many thanks in advance
Don

I expect to do Check_Tenant_Expiry and after it completed it will continue with Run_Daily_Report
You shouldn't use ContinueWith for this. ContinueWith is a low-level method with dangerous default behavior. At the very least, you must pass a TaskScheduler. In addition, ContinueWith doesn't understand asynchronous code, so if you pass async code in, you'll also need to use Unwrap.
Instead, you should just use await, which is simpler, more maintainable, and does the right thing by default:
bool _xxx = await Check_Tenant_Expiry();
await Run_Daily_Report(_xxx);
On a side note, this seems suspect:
return await Task.FromResult(_ret);
That's literally a less efficient form of this:
return _ret;
I suspect that the await Task.FromResult was added to avoid a compiler warning telling you that the method will run synchronously. If you were in fact getting that warning, then the proper solution is to either make the method properly asynchronous (not adding an await just to make the warning go away), or to remove the async and leave the method synchronous.

Try this
await Check_Tenant_Expiry().ContinueWith( async (t) =>
{
await Run_Daily_Report();
}, TaskContinuationOptions.OnlyOnRanToCompletion);

You made a function with async keyword, which means you told compiler excute "Run_Daily_Reporty" method by asynchronously. But you didn't execute the method with await keyword, which means It's run by synchronously. That's why compiler told you "it's right?"
Try this
// You must use async keyword when you want to use await keyword in lambda function.
await Check_Tenant_Expiry().ContinueWith(async(t) =>
{
await Run_Daily_Report(t.Result);
}, TaskContinuationOptions.OnlyOnRanToCompletion);
I think you made code the way you wanted to work.
I think you might not know the async/await keywords yet.
They can make your asynchronous code looks like synchronous code that we've been making every day, which means it's way more easy to understand.
How about making code like below. It's going to make the same result with the code you made.
bool result = await Check_Tenant_Expiry();
await Run_Daily_Report(result);

Related

Waiting for a Task conditionally

For an async method that returns a Task<bool>, I need to take some actions when the method completes. The async method looks like this:
async Task<bool> EntryExists(string entry)
{
return await Task.Run(() => call_that_returns_bool());
}
I call it and attach a continuation task to it to perform follow-up actions:
EntryExists(my_entry).ContinueWith(t =>
{
if(t.Result) ...
});
However, I now need to conditionally wait for chained task to complete. Means depending upon a parameter, I either need to return immediately to the caller, or wait till the tasks finish. I change the above code to look like this:
var T = EntryExists(my_entry).ContinueWith(t =>
{
if(t.Result) ...
});
if(wait) T.Wait(); //wait is my parameter
Running this, the code gets stuck forever at T.Wait() when wait parameter is true, as if T never kicked off. I then tried the following:
var T = EntryExists(my_entry).ContinueWith(t =>
{
if(t.Result) ...
});
T.Start();
if(wait) T.Wait();
Upon which it tells me that
Start may not be called on a continuation task
I know I'm missing something basic, but after been coding for the last 15 hours, my brain isn't helping much. Can someone point out what I need to do?
You shouldn't block on async code. In short, you're very likely to be blocking the thread that the async method needs to return to (in this case you are, as it's the UI thread). The solution is to use async-await all the way through, rather than trying to run it synchronously. If you absolutely have to present a synchronous method, then at least provide as simpler wrapper as possible, rather than mixing ContinueWith and async-await.
Your outer call can be rewritten as:
async Task<{something}> MakeCallAndContinue()
{
try
{
await EntryExists(my_entry);
// additional continuation code
}
catch (Exception e)
{
// handle in some way
}
}
var task = MakeCallAndContinue();
if (wait) await task;
It's unusual to want to start a task and then not await it, which is what you're doing if wait is false. The error handler I've put in the above code is to ensure that you don't get an exception thrown on to an unawaited task. If you did that, then it would be thrown out somewhere else, and probably kill your process if you haven't declared a global handler.
You won't be able to use the above in your WPF command as-is, because it's async. However, you can have async WPF command handlers, as explained here. If you did want to do it synchronously then you would need to call .Wait(), but as Stephen Cleary explains in my first link, you have to use ConfigureAwait(false) on all awaited tasks all the way down in order to prevent one of them from trying to return to the occupied UI thread, and deadlocking.

async/await mechanism in C#

I have 2 questions that I would like to ask.
I've read this paragraph in Microsoft documents about async/await. But I did not understand it clearly.
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/task-asynchronous-programming-model#BKMK_APIAsyncMethods
"If GetStringAsync (and therefore getStringTask) completes before AccessTheWebAsync awaits it, control remains in AccessTheWebAsync. The expense of suspending and then returning to AccessTheWebAsync would be wasted if the called asynchronous process (getStringTask) has already completed and AccessTheWebSync doesn't have to wait for the final result."
Could you please explain it?
As I read, when you use async/await in C#, the code is not running in two separate threads. It still in synchronous context, but it'll return Task in the case it meets "await" keyword as a promise that result will be returned until it completed. If the task completes before "await", it's now the same with synchronous. No differences. Even it's costly to switch from the caller method to "AccessTheWebAsync" method and vice versa.
Sorry, this is the first time I ask questions on StackOverflow.
Given the function:
async Task<int> AccessTheWebAsync()
{
// You need to add a reference to System.Net.Http to declare client.
using (HttpClient client = new HttpClient())
{
Task<string> getStringTask = client.GetStringAsync("https://learn.microsoft.com");
DoIndependentWork();
string urlContents = await getStringTask;
return urlContents.Length;
}
}
When execution gets to
string urlContents = await getStringTask;
the execution can do one of 2 things:
If GetStringAsync() has already completed, the execution continues with the next line (return urlContents.Length; )
If GetStringAsync() has not completed, then execution of AccessTheWebAsync() is suspended and execution returns to the calling function until GetStringAsync() completes. The paragraph your asking about is stating that If we suspended the execution of AccessTheWebAsync() anyway, the expense of suspending and then returning to AccessTheWebAsync would be wasted. Therefor this doesn't happen, as it is smart enough to know when to suspend execution and when not to.
An async method in C# must always return a Task and looks like this:
public async Task method();
public async Task<bool> asyncMethod();
When it doesn't return anything, so void just return Task and in any other case Task<returntype>
When you call upon an async method, you can do either 3 things:
// Result is now of type Task<object> and will run async with any code beyond this line.
// So using result in the code might result in it still being null or false.
var result = asyncMethod();
// Result is now type object, and any code below this line will wait for this to be executed.
// However the method that contains this code, must now also be async.
var result = await asyncMethod();
// Result is now type Task<object>, but result is bool, any code below this line will wait.
// The method with this code does not require to be async.
var result = asyncMethod().Result;
So to answer your questions.
Consider whether the result of the executed code is used elsewhere in the code, because if you don't await it, the result will be wasted, since it will still be null.
Same goes the other way around, when awaiting a method that won't return anything, then awaiting is usually not necessary.

Does the following code sequence make sense in C#

I haven't used async/await very often and I'm not fully comfortable with them. I am trying to make an operation that is synchronous to be run asynchronously. Can you tell me if the following code snippet makes sense:
public static async Task<string> FileVersionAsync(string localFilePath)
{
FileVersionInfo versionInfo;
try
{
versionInfo = await Task.FromResult(FileVersionInfo.GetVersionInfo(localFilePath));
}
catch (SecurityException)
{
return "File Version Checker does not have permission to read file version";
}
catch (FileNotFoundException)
{
return "Unable to find configured file";
}
if (versionInfo.FileVersion == null)
return "N/A";
return versionInfo.FileVersion;
}
Adding Task, await and async do not make something asynchronous; they merely provide the plumbing to work with asynchronous code when it happens. In your example: it never happens asynchronously, so all you are doing is adding plumbing overhead for no benefit.
The compiler will generate a ton of extra code that will turn out to never be hit, because when it gets to the await it'll discover that the task is already complete, and will simply continue on the existing thread.
To actually be asynchronous, you need ... something that is async. This could be external IO, or could be something threading related - but note that simply jumping to another thread doesn't buy you anything: it just adds a context switch.
If there was a FileVersionInfo.GetVersionInfoAsync method, what you are doing might be worthwhile.
No it does not make sense.
The only reason to make your function async is if somewhere inside it awaits other functions that are async. In fact your compiler warns you if you forget to await somewhere.
The async-await syntax was invented as a replacement for other task functions like Task.ContinueWith, Task.FromResult, Task.FromException etc.
In this interview Eric Lippert compared async-await with a cook who has to prepare breakfast Search somewhere in the middle for async-await.
If a cook has to prepare breakfase he starts to boil water. But instead of waiting for the water to cook, he starts slicing bread, and do other things. Only after he has nothing to do anymore he starts waiting idly for the water to boil after which he makes the tea.
Similarly: if a program has to wait for an external process to perform a request, like a database query, write data to a file, get information from the internet etc. async-await makes sure that your thread doesn't wait idly. Instead your thread goes up its call stack to see if one of the callers can continue working without the result from the other process.
You'll see this in the following code:
public async Task<string> ReadTextFile()
{
StreamReader txtReader = File.OpenText(...);
// read the complete text file; don't wait until finished yet
Task<String> taskTxt = txtReader.ReadToEndAsync();
// as we didn't use await, we can continue processing:
DoSomething();
// now we need the result from the read action: await for it
// the result of await Task<TResult> is the TResult:
string importedTxt = await taskTxt;
return importedTxt;
}
Some guidelines for async-await:
Only use async-await if you call at least one other async function
instead of void return Task, instead of TResult return Task<TResult>
Only exception: the async event handler: this async function returns void
The return of await Task is void; the return of await Task<TResult> is TResult
If you don't need the result of an async function right now, and if you can do something meaningful while the task is processing: start the task by calling the async function, but don't await for it. Only await when you need the result
.
public async void Button_Clicked(object sender, EventArgs e)
{
// indicate you will do something time consuming:
this.ProgressBar1.Visible = true;
await DoSomethingTimeconsumingAsync(...);
// finished:
this.progressBar1.Visible = false;
}
This will make sure that whenever your thread has to wait something, it can do other things, and thus your GUI remains responsive.
No. There appears to be absolutely no need to make this method async, because Task.FromResult is ready immediately.

Async/Await VS Task.Run : When to use ? How to use?

Okay I hope I got the basics of async/await but still some questions a re lingering in my head.
But now it is the problem I am talking about . Suppose in this simple example
static void Main(string[] args)
{
Method();
Console.WriteLine("Main Thread");
Console.ReadLine();
}
public async static void Method()
{
await Task.Run(new Action(LongTask));
Console.WriteLine("New Thread");
}
public static void LongTask()
{
Thread.Sleep(8000);
Console.WriteLine("Long Task");
}
The main thread still continues and prints Main Thread after calling Method() and encountering an await for 8 seconds .
So accordingly the Method() returns to the caller i.e. to the main function here once it encounters await , saves the synch context and keeps on executing from there .
It prints Main Thread first .
Then after 8 seconds complete , Long Task and then New Thread get printed.
This part I got . My question is in my application :
public IList<createcaseoutput> createCase(CreateCaseInput CreateCaseInput,SaveCaseSearchInput SaveCaseSearchInput)
{
.............
SQL.CaseSQL.getCreateCaseParameters(CreateCaseInput, out strSPQuery, out listParam);
var AcctLst = rep.ExecuteStoredProcedure<createcaseoutput>(strSPQuery, listParam).ToList();
if (!string.IsNullOrEmpty(AcctLst.ElementAt(0).o_case_seq.ToString()))
{
await saveCaseSearch(SaveCaseSearchInput, AcctLst.ElementAt(0).o_case_seq);
}
console.writeline("Async called");
return AcctLst;
}
public async Task<ilist<savecasesearchoutput>> saveCaseSearch(SaveCaseSearchInput SaveCaseSearchInput,Int64? case_key)
{
..........................
SQL.CaseSQL.getSaveCaseSearchParameters(SaveCaseSearchInput, case_key, out strSPQuery, out listParam);
var AcctLst = await rep.ExecuteStoredProcedureAsync<entities.case.savecasesearchoutput>(strSPQuery, listParam);
return AcctLst;
}
Here also createCase is encountering await and
it should return immediately right and execute the very next line itself and print Async called
before even the SaveCaseSearch completes right ?
Okay if I am thinking loud it might be control returns to the caller .
So is it like if I wrap my call SavCaseSearch inside another async/await method named suppose
async DoWork() {....
}
and call this DoWork() from CreateCase() directly so then
It will go on printing "Async called" once call to DoWork() encounters await and before it even completes ?
Am I thinking in the correct way ?
Also sometimes I see and get confused between
await someAsync()
and
await Task.Run(() => someAsync()) ..
what's the difference between them ? and which one to follow ?
My question is in my application :
Your code won't compile because you're using await without async. Corrected code would be:
public async Task<IList<createcaseoutput>> createCaseAsync(CreateCaseInput CreateCaseInput,SaveCaseSearchInput SaveCaseSearchInput)
{
...
await saveCaseSearch(SaveCaseSearchInput, AcctLst.ElementAt(0).o_case_seq);
console.writeline("Async called");
return AcctLst;
}
Here also createCase is encountering await and it should return immediately right and execute the very next line itself and print Async called before even the SaveCaseSearch completes right ?
No. This code:
await saveCaseSearch(SaveCaseSearchInput, AcctLst.ElementAt(0).o_case_seq);
is the same as this code:
var saveTask = saveCaseSearchAsync(SaveCaseSearchInput, AcctLst.ElementAt(0).o_case_seq);
await saveTask;
So, first, createCaseAsync would call saveCaseSearchAsync. Presumably, saveCaseSearchAsync is performing some asynchronous operation, so it will return an incomplete task to createCaseAsync. createCaseAsync then awaits that task, which causes it to return an incomplete task to its caller.
Eventually, saveCaseSearchAsync will complete, which will complete the task it returned (which I called saveTask in the code above). This in turn will continue executing createCaseAsync, and it will proceed to the next line and print "Async called" on the console.
So is it like if I wrap my call SavCaseSearch inside another async/await method
You wouldn't need a wrapper because createCaseAsync is already returning a Task.
what's the difference between them ? and which one to follow ?
Task.Run is mainly for pushing blocking work off the UI thread and onto the threadpool. Since you're on ASP.NET, don't use Task.Run.
The first rule of async is to always use async or never use async.
If your underlying API can't handle async it's no use to use async in the upper layers (like ASP.NET MVC), since at some point you'll get thread starvation as all threads are occupied waiting on IO operations (like DB calls).
Your example is a classical case where you mix sync and async. The Sleep call will lock the thread until it completes. You should have used Task.Delay instead as it would have released the thread until the delay completes.
My advice to you is to simply start by following the rule I mentioned first and only when IO bound operations like DB or file calls are involved. Then when you understand async better you can start to break it since you then have a much better understanding in what it can lead to.
(Sorry for not answering your questions directly, but threading is a complex topic and your brain can fry if you try to get it all in directly. Start small.)
Here also createCase is encountering await and it should return immediately right and execute the very next line itself and print Async called before even the SaveCaseSearch completes right ?
This shouldn't even compile. The 'await' operator can only be use within an 'async' method. That said, if you remove the 'await' operator, then the next line will print "Async called" before even the saveCaseSearch completes.
Am I thinking in the correct way ?
saveCaseSearch is already an 'async' method, so you don't need to wrap it to achieve the desired result. That said, you could wrap it in another method, if you really want to.
what's the difference between them ? and which one to follow ?
The 'await' operator wait for a Task object so either one is fine. I would chose await someAsync(), because it's less code to write.
Regarding the difference between async/await and Tasks...
Async/Await are syntactic keywords to simplify your code, as everything before the await keyword happens in the calling thread and everything from the await onward happens is in the task's continuation.
Setting this up with tasks using the TPL will require a lot of code and readability suffers. Note however, Underneath it is still using Tasks and Continuations.
Further, they cannot always be used in place of Tasks like when the completion of Task is nondeterministic, or if you have multiple levels of Tasks along with the usage of TaskCompletionSource.
For more information read the chapter 4 "Asynchronous Programming" in the book "Writing High-Performance .NET Code" by Ben Watson
Note also, Internally, the TPL uses the .NET thread pool, but does so more intelligently, by executing multiple Tasks on the same thread sequentially before returning the thread back to the pool. It can do this via intelligent use of delegate objects.

How do I start not-awaited background tasks in an async method?

I'm struggling with how to perform some very-long-running background processing in a world of async methods.
Using the vocabulary from Stephen Cleary's blog, I'm interested in kicking off a "delegate task" after await-ing a "promise task". I want to return the promised value as soon as it's available, and let the delegate task continue on in the background.
To handle exceptions in the un-await-ed delegate task, I'll use an exception-handling continuation modeled after the one described here.
public async Task<int> ComplexProcessAsync()
{
...
int firstResult = await FirstStepAsync();
// THE COMPILER DOESN'T LIKE THIS
Task.Run(() => VeryLongSecondStepIDontNeedToWaitFor(firstResult)).LogExceptions();
return firstResult;
}
Since VeryLongSecondStep...() could take many minutes, and its results are observable purely by side-effect (e.g. records appearing in a database), I reeeaaalllyy don't want to await it.
But as pointed out, the compiler doesn't like this. It warns "Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call."
I could ignore the warning, but I get the feeling I'm not doing this in "correct" way. So what is the correct way?
Thanks!
I could ignore the warning, but I get the feeling I'm not doing this in "correct" way. So what is the correct way?
The compiler is warning you that you're not awaiting the task. From my experience, >99% of the time the compiler is correct, the code is wrong because it's missing an await. So this is one of the rare situations where you know what you're doing and want to live dangerously. :)
In this case, you can explicitly assign the task to an unused variable:
var _ = Task.Run(() => VeryLongSecondStepIDontNeedToWaitFor(firstResult));
The compiler is intelligent enough to understand that you're using this variable to silence the "missing await" warning.
On a side note, I do not recommend ContinueWith at all; in the async world, it's just a more dangerous version of await. So I'd write LogExceptions something like this:
public static async Task LogExceptions(this Task task)
{
try
{
await task.ConfigureAwait(false);
}
catch (Exception ex)
{
LogException(ex);
}
}
Since this is within an ASP.NET Web API app I suggest you use HostingEnvironment.QueueBackgroundWorkItem. Stephen Cleary also has a post about it.
HostingEnvironment.QueueBackgroundWorkItem(ct =>
{
try
{
// your code
}
catch (Exception ex)
{
// handle & log exception
}
});
https://msdn.microsoft.com/en-us/library/dn636893(v=vs.110).aspx
http://blog.stephencleary.com/2014/06/fire-and-forget-on-asp-net.html
The compiler is trying to protect you from mistakes because it's really easy to forget the await when you actually need to await something, but in this case you really don't need the await, so you can ignore the warning.
However, in this case I think it's a better idea to run the task on some thread from the threadpool, because if you're running it on the main thread like you're doing now, you might cause your application to be non-responsive for new incoming requests/events.
I'd like to suggest you to move VeryLongSecondStepIDontNeedToWaitFor() out of the ComplexProcessAsync() method.
ComplexProcessAsync() itself returns a value, that is being used by at least two tasks (one of them is Task.Run(() => VeryLongSecondStepIDontNeedToWaitFor(firstResult))).
You can combine these tasks via Task.WhenAny():
var result = await ComplexProcessAsync();
await Task.WhenAny(VeryLongSecondStepIDontNeedToWaitFor(firstResult), YourSecondMethod(firstResult))
where YourSecondMethod(firstResult) is the method that uses the ComplexProcessAsync() result.

Categories