Task.wait vs async await - c#

I have been looking into upgrading the way that we do async tasks in our software. For years the software has been running in .net 2.5 and the team previous, decided to implement their own async task architecture which for the most part is OK but difficult to use for more complicated things.
I was watching a tutorial which explained tasks in C# really well but then started looking at async methods and the await keyword to keep the software up to date. My question is, why you would want to use async and await over just creating a task and using .wait/.waitAll/.waitAny.
I have read things that say that it isn't creating new threads (which suggests its not as parallel) and that it has a performance overhead.
Can you still apply the wait all one by one methodology? I am guessing since the async returns a task you would just use this to populate your list but that just furthers my argument on why would you bother using it?

My question is, why you would want to use async and await over just
creating a task and using .wait/.waitAll/.waitAny.
A task is merely a promise of your which will complete in the future. Task != Thread , and that is an important thing to remember.
I have read things that say that it isn't creating new threads (which
suggests its not as parallel) and that it has a performance overhead.
That depends on how the Task is being created.
For example:
public async Task<string> GetPageAsync(string url)
{
var httpClient = new HttpClient();
var response = await httpClient.GetAsync(url);
return response.Content.ReadAsStringAsync();
}
This operations generates no threads, but still returns a Task<string>. using async-await has some overhead because under the covers, the compiler creates a state-machine which manages the execution flow, which has to take care of many things.
While this:
return Task.Run(FooOperation);
Requests a thread pool thread to run FooOperation on.
A task can be generated for doing overlapped IO (like the first example) operations which require no thread at all. When you create a task and use Wait/WaitAll/WaitAny, you're blocking on the call, and then you end up asking yourself why use that at all and not run it synchronously instead?
For async-await, you can use the asynchronous WhenAny/WhenAll, which themselfs yield an awaitable which can be asynchronously waited.

Related

Does async (one task) make sense in MVC?

I am using async/await in MVC, but only when I have more than one task (WaitAll).
I understand that having only one task is good to have the UI free, in case of WPF or Windows Form, but does it make sense for MVC to have only one task and await for that?
I've seen it a lot in code, in MVC, but I don't get the advantages.
HTTP requests are handled by thread pool threads.
If you block a thread, it will not be able to do other work. Because the total number of threads is limited, this can led to the starvation of the thread pool and new requests will be denied - 503.
Using async code, the thread is released back to the thread pool, becoming available to handle new requests or the continuations of async code.
Like on client UIs, on the server, async code is all about responsiveness, not performance. Requests will take longer but your server will be able to handle more requests.
It depends on what you are trying to achieve. For instance, if you have multiple calls to multiple services you can always do it in a way that only the last call makes the rest of the system "wait".
You can optimise your code in a way that X asynchronously calls to services start (almost) at the same time without having to 'await' for one another.
public async Task RunSomethings()
{
var something1 = AsyncCall1();
var something2 = AsyncCall2();
var something3 = await AsyncCall3();
}
private async Task<Something1> AsyncCall1()
{
return await Something1();
}
private async Task<Something2> AsyncCall2()
{
return await Something2();
}
private async Task<Something3> AsyncCall3()
{
return await Something3();
}
I hope it helps.
Good question. Using asynchronous methods is all about using the resources effectively as well as give a good user experience. Any time you need to call on a resource that could take time to collect, it's good to use an async call.
This will do a few things. First, while a worker thread is waiting for data, it can be put on 'hold' so to speak, and that worker thread can do something else until the data is returned, an error is returned or the call just times out.
This will give you the second advantage. The interface the user is using to call the resource will be released, temporarily, to do other things. And overall, less server resources are consumed by idle processes.
I'd recommend watching the videos on this page here: https://channel9.msdn.com/Series/Three-Essential-Tips-for-Async
It's probably the clearest explanation that can help leapfrog your learning on async.

creating a threadless task using Taskcompletion source

I am getting my hands dirty with TPL.I stumbled upon a topic in TPL called TaskCompletionSource which is one of the ways to create a Task and it give you more control over the task by allowing developers in setting result,exception etc etc. Here is an example using task completion source
public static Task<int> RunAsyncFunction(Func<int> sampleFunction)
{
if (sampleFunction == null)
throw new NullReferenceException("Method cannot be null");
var tcs = new TaskCompletionSource<int>();
ThreadPool.QueueUserWorkItem(_ =>
{
try
{
int result = sampleFunction();
tcs.SetResult(result);
}
catch (Exception ex)
{
tcs.SetException(ex);
}
});
return tcs.Task;
}
However this is not truly asynchronus programming.It is asynchronus programming using multithreading .How can I convert this example to get it run on a single thread rather than multiple threads ? or is there any other example I can follow?
For it to be asynchronous, it needs some capacity to be completed independently in the future. That is typically via one of two things:
via a callback from an operation such as socket IO, file IO, a system timer, etc (some external source that can cause reactivation)
a second thread (possibly a queued work pool thread, like in your example)
If you only have a single thread, and no external callback, then there really isn't any need or sense in using Task<T>. However, you can still expose that by simply performing the calculation now, and setting the result now - or more simply: using Task.FromResult.
However, the code you have shown is genuinely asynchronous - or more specifically: the Task<T> that you return is. It perhaps isn't the greatest use-case, but there's nothing inherently wrong with it - except that your entire method can be hugely simplified to:
return Task.Run(sampleFunction);
The Task.Run<T> method:
Queues the specified work to run on the ThreadPool and returns a task or Task handle for that work.
Normally, if I'm using TaskCompletionSource, it is because I am writing IO-callback based tasks, not ThreadPool based tasks; Task.Run is fine for most of those.
TaskCompletionSource doesn't make your code asynchronous. It's a utility to enable someone else to asynchronously await your operation.
Your operation needs to already be asynchronous on its own. For example if it's in an older paradigm, like the BeginXXX/EndXXX one.
TaskCompletionSource is mostly used to convert different types of asynchronous programming into Task based asynchronous programming.

New Methods: Implementing INFINITE LOOP which can be STOPPED upon request

What is the correct method to implement a infinitely running task which executes an Async BigJob()? and can be stopped upon request
Hint: I am trying to learn [a] new method(s) to update my existing strategy.
I have this simple program (a tester) which has an Start and Stop button.
When Start pressed, I am starting the tester which is going to find and test available devices in range and test the hell our of them in infinite amount of rounds until the user presses the Stop button.
The important point is, the main process/action/bigJob() is and awaitble asynchronous process.
So I would pseudo code the whole thing as
Start
Round 1 starts
Async Main job starts
Async connect
Async Read
Async Write
Async disconnect
Nobody cancelled me yet
Round 1 finishes
Round 2 starts
.
.
.
Round 2 finishes
Round 3 starts
.
Stop pressed, hence break out.
Stop
So I am using BackgroundWorker to implement the infinite loop and Async/Await for the Connect, read, write and disconnect that I have written in C# under .Net 4.5
Since my sub-tasks such as Connect and .etc are async then my main task is async and pressing the Stop button stops my process since it eliminates the infinite while loop that I have with having
while (!bw.CancellationPending)
{
await MainTask();
...
}
but it doesn't fire the BackgroundWorker_RunWorkerCompleted event, which doesn't do me any harm HOWEVER it's killing me since the background worker doesn't work as it's supposed to and I just keep thinking "there should be a better way!".
So, I have been reading about so many new ideas, like why to use BackgroundWorker at all now that we have Async/await. Some were saying use Task.Run() it's magical. I even read recommendations and blogs about this godsend TPL Dataflow that I have never heard of. And so far I haven't found a method which is as structured, documented and layed-out as a BackgroundWorker. (unless it's such simple or a one liner which doesn't even need documentation or .etc) So, guys, what is the solution for this. Or better way to ask:
What is the correct method to implement a infinitely running task which executes an Async BigJob()? and can be stopped upon request
You should use CancellationTokenSource. But don't pass the Token to the Task.Run method and don't throw an exception. Simply check if cancellation was requested and then stop.
CancellationTokenSource cts = new CancellationTokenSource();
CancellationToken ct = cts.Token;
Task.Run(
async () =>
{
while (!ct.IsCancellationRequested)
{
await ConnectAsync();
await ReadAsync();
await WriteAsync();
await DisconnectAsync();
}
});
cts.Cancel();
When you pass a CancellationToken to the Task itself(Task.Run(async () => ..., ct)), you can't use it inside the delegate. It will only cancel the task if cancellation was called before the task started running. After it has begun, calling Cancel won't have any effect.
Create a CancellationTokenSource and pass its Token to the async task. This will allow you to signal to your async tasks that cancellation is requested. More info: http://msdn.microsoft.com/en-us/library/hh873177(v=vs.110).aspx
I would strongly recommend everybody to have a read about three different methods of Asynchronous Programming Patterns and the use of the recent and preferred method Task-based Asynchronous Pattern (TAP)
Asynchronous Programming Model (APM)
Describes the legacy model that uses the IAsyncResult interface to
provide asynchronous behavior. This model is no longer recommended for
new development.
Event-based Asynchronous Pattern (EAP)
Describes the event-based legacy model for providing asynchronous
behavior. This model is no longer recommended for new development.
Task-based Asynchronous Pattern (TAP)
Describes the new asynchronous pattern based on the
System.Threading.Tasks namespace. This model is the recommended
approach to asynchronous programming in the .NET Framework 4 and later
versions.
Thanks to #SKall for pointing me to the right direction.

When would I use Task.Yield()?

I'm using async/await and Task a lot but have never been using Task.Yield() and to be honest even with all the explanations I do not understand why I would need this method.
Can somebody give a good example where Yield() is required?
When you use async/await, there is no guarantee that the method you call when you do await FooAsync() will actually run asynchronously. The internal implementation is free to return using a completely synchronous path.
If you're making an API where it's critical that you don't block and you run some code asynchronously, and there's a chance that the called method will run synchronously (effectively blocking), using await Task.Yield() will force your method to be asynchronous, and return control at that point. The rest of the code will execute at a later time (at which point, it still may run synchronously) on the current context.
This can also be useful if you make an asynchronous method that requires some "long running" initialization, ie:
private async void button_Click(object sender, EventArgs e)
{
await Task.Yield(); // Make us async right away
var data = ExecuteFooOnUIThread(); // This will run on the UI thread at some point later
await UseDataAsync(data);
}
Without the Task.Yield() call, the method will execute synchronously all the way up to the first call to await.
Internally, await Task.Yield() simply queues the continuation on either the current synchronization context or on a random pool thread, if SynchronizationContext.Current is null.
It is efficiently implemented as custom awaiter. A less efficient code producing the identical effect might be as simple as this:
var tcs = new TaskCompletionSource<bool>();
var sc = SynchronizationContext.Current;
if (sc != null)
sc.Post(_ => tcs.SetResult(true), null);
else
ThreadPool.QueueUserWorkItem(_ => tcs.SetResult(true));
await tcs.Task;
Task.Yield() can be used as a short-cut for some weird execution flow alterations. For example:
async Task DoDialogAsync()
{
var dialog = new Form();
Func<Task> showAsync = async () =>
{
await Task.Yield();
dialog.ShowDialog();
}
var dialogTask = showAsync();
await Task.Yield();
// now we're on the dialog's nested message loop started by dialog.ShowDialog
MessageBox.Show("The dialog is visible, click OK to close");
dialog.Close();
await dialogTask;
// we're back to the main message loop
}
That said, I can't think of any case where Task.Yield() cannot be replaced with Task.Factory.StartNew w/ proper task scheduler.
See also:
"await Task.Yield()" and its alternatives
Task.Yield - real usages?
One use of Task.Yield() is to prevent a stack overflow when doing async recursion. Task.Yield() prevents syncronous continuation. Note, however, that this can cause an OutOfMemory exception (as noted by Triynko). Endless recursion is still not safe and you're probably better off rewriting the recursion as a loop.
private static void Main()
{
RecursiveMethod().Wait();
}
private static async Task RecursiveMethod()
{
await Task.Delay(1);
//await Task.Yield(); // Uncomment this line to prevent stackoverlfow.
await RecursiveMethod();
}
Task.Yield() is like a counterpart of Thread.Yield() in async-await but with much more specific conditions. How many times do you even need Thread.Yield()? I will answer the title "when would you use Task.Yield()" broadly first. You would when the following conditions are fulfilled:
want to return the control to the async context (suggesting the task scheduler to execute other tasks in the queue first)
need to continue in the async context
prefer to continue immediately when the task scheduler is free
do not want to be cancelled
prefer shorter code
The term "async context" here means "SynchronizationContext first then TaskScheduler". It was used by Stephen Cleary.
Task.Yield() is approximately doing this (many posts get it slightly wrong here and there):
await Task.Factory.StartNew(
() => {},
CancellationToken.None,
TaskCreationOptions.PreferFairness,
SynchronizationContext.Current != null?
TaskScheduler.FromCurrentSynchronizationContext():
TaskScheduler.Current);
If any one of the conditions is broken, you need to use other alternatives instead.
If the continuation of a task should be in Task.DefaultScheduler, you normally use ConfigureAwait(false). On the contrary, Task.Yield() gives you an awaitable not having ConfigureAwait(bool). You need to use the approximated code with TaskScheduler.Default.
If Task.Yield() obstructs the queue, you need to restructure your code instead as explained by noseratio.
If you need the continuation to happen much later, say, in the order of millisecond, you would use Task.Delay.
If you want the task to be cancellable in the queue but do not want to check the cancellation token nor throw an exception yourself, you need to use the approximated code with a cancellation token.
Task.Yield() is so niche and easily dodged. I only have one imaginary example by mixing my experience. It is to solve an async dining philosopher problem constrained by a custom scheduler. In my multi-thread helper library InSync, it supports unordered acquisitions of async locks. It enqueues an async acquisition if the current one failed. The code is here. It needs ConfigureAwait(false) as a general purpose library so I need to use Task.Factory.StartNew. In a closed source project, my program needs to execute significant synchronous code mixed with async code with
a high thread priority for semi-realtime work
a low thread priority for some background work
a normal thread priority for UI
Thus, I need a custom scheduler. I could easily imagine some poor developers somehow need to mix sync and async code together with some special schedulers in a parallel universe (one universe probably does not contain such developers); but why wouldn't they just use the more robust approximated code so they do not need to write a lengthy comment to explain why and what it does?
Task.Yield() may be used in mock implementations of async methods.

Wrapping synchronous code into asynchronous call

I have a method in ASP.NET application, that consumes quite a lot of time to complete. A call to this method might occur up to 3 times during one user request, depending on the cache state and parameters that user provides. Each call takes about 1-2 seconds to complete. The method itself is synchronous call to the service and there is no possibility to override the implementation.
So the synchronous call to the service looks something like the following:
public OutputModel Calculate(InputModel input)
{
// do some stuff
return Service.LongRunningCall(input);
}
And the usage of the method is (note, that call of method may happen more than once):
private void MakeRequest()
{
// a lot of other stuff: preparing requests, sending/processing other requests, etc.
var myOutput = Calculate(myInput);
// stuff again
}
I tried to change the implementation from my side to provide simultaneous work of this method, and here is what I came to so far.
public async Task<OutputModel> CalculateAsync(InputModel input)
{
return await Task.Run(() =>
{
return Calculate(input);
});
}
Usage (part of "do other stuff" code runs simultaneously with the call to service):
private async Task MakeRequest()
{
// do some stuff
var task = CalculateAsync(myInput);
// do other stuff
var myOutput = await task;
// some more stuff
}
My question: Do I use the right approach to speed up the execution in ASP.NET application or am I doing unnecessary job trying to run synchronous code asynchronously?
Can anyone explain why the second approach is not an option in ASP.NET (if it is really not)?
Also, if such approach is applicable, do I need to call such method asynchronously if it is the only call we might perform at the moment (I have such case, when no other stuff there is to do while waiting for completion)?
Most of the articles in the net on this topic covers using async-await approach with the code, that already provides awaitable methods, but that's not my case. Here is the nice article describing my case, which doesn't describe the situation of parallel calls, declining the option to wrap sync call, but in my opinion my situation is exactly the occasion to do it.
It's important to make a distinction between two different types of concurrency. Asynchronous concurrency is when you have multiple asynchronous operations in flight (and since each operation is asynchronous, none of them are actually using a thread). Parallel concurrency is when you have multiple threads each doing a separate operation.
The first thing to do is re-evaluate this assumption:
The method itself is synchronous call to the service and there is no possibility to override the implementation.
If your "service" is a web service or anything else that is I/O-bound, then the best solution is to write an asynchronous API for it.
I'll proceed with the assumption that your "service" is a CPU-bound operation that must execute on the same machine as the web server.
If that's the case, then the next thing to evaluate is another assumption:
I need the request to execute faster.
Are you absolutely sure that's what you need to do? Are there any front-end changes you can make instead - e.g., start the request and allow the user to do other work while it's processing?
I'll proceed with the assumption that yes, you really do need to make the individual request execute faster.
In this case, you'll need to execute parallel code on your web server. This is most definitely not recommended in general because the parallel code will be using threads that ASP.NET may need to handle other requests, and by removing/adding threads it will throw the ASP.NET threadpool heuristics off. So, this decision does have an impact on your entire server.
When you use parallel code on ASP.NET, you are making the decision to really limit the scalability of your web app. You also may see a fair amount of thread churn, especially if your requests are bursty at all. I recommend only using parallel code on ASP.NET if you know that the number of simultaneous users will be quite low (i.e., not a public server).
So, if you get this far, and you're sure you want to do parallel processing on ASP.NET, then you have a couple of options.
One of the easier methods is to use Task.Run, very similar to your existing code. However, I do not recommend implementing a CalculateAsync method since that implies the processing is asynchronous (which it is not). Instead, use Task.Run at the point of the call:
private async Task MakeRequest()
{
// do some stuff
var task = Task.Run(() => Calculate(myInput));
// do other stuff
var myOutput = await task;
// some more stuff
}
Alternatively, if it works well with your code, you can use the Parallel type, i.e., Parallel.For, Parallel.ForEach, or Parallel.Invoke. The advantage to the Parallel code is that the request thread is used as one of the parallel threads, and then resumes executing in the thread context (there's less context switching than the async example):
private void MakeRequest()
{
Parallel.Invoke(() => Calculate(myInput1),
() => Calculate(myInput2),
() => Calculate(myInput3));
}
I do not recommend using Parallel LINQ (PLINQ) on ASP.NET at all.
I found that the following code can convert a Task to always run asynchronously
private static async Task<T> ForceAsync<T>(Func<Task<T>> func)
{
await Task.Yield();
return await func();
}
and I have used it in the following manner
await ForceAsync(() => AsyncTaskWithNoAwaits())
This will execute any Task asynchronously so you can combine them in WhenAll, WhenAny scenarios and other uses.
You could also simply add the Task.Yield() as the first line of your called code.
this is probably the easiest generic way in your case
return await new Task(
new Action(
delegate () {
// put your synchronous code here
}
)
);

Categories

Resources