Difference between Task.Start and using discard - c#

I have a Task that does not return a result, and no other code is dependent on it completing, like this:
private async Task PerformMyTaskAsync(CancellationToken CancellationToken)
{
bool IsComplete = false;
while (!IsComplete && !CancellationToken.IsCancellationRequested)
{
//Do stuff until Complete or Cancelled
}
}
I have be using the discard to run it, like this:
_ = PerformMyTaskAsync(CancellationToken);
which works OK, but recently I discovered Task.Start. I know using Task.Start gives me the option of monitoring the task (if I store the result), but in this case, is there any difference between discard and this?
PerformMyTaskAsync(CancellationToken).Start();
Is it better practice to use discard as it's the newer feature?

PerformMyTaskAsync(CancellationToken).Start() doesn't do what you want, so: don't do that! PerformMyTaskAsync(CancellationToken) will return an initialized working operation - it has already been started, because you just did that - calling .Start() will throw InvalidOperationException citing "Start may not be called on a promise-style task".
Discard itself doesn't do anything except tell the compiler "I meant to do this", which is basically just a way of saying "I don't want to await this" to suppress a compiler 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."). You can do that with the result of Task.Run, too - and should do in exactly the same scenarios.
So the real question here is Task.Run vs direct invoke; for that, the main difference is "how much of it runs now?". When invoking it directly, it will run on the current thread until the first incomplete await - at which point the async machinery kicks in. That can mean it runs to completion, and with a while loop could mean it effectively runs forever (for example if the loop incorrectly uses Thread.Sleep() instead of Task.Delay() for pausing). If you don't want any of it to run on the current thread, or you want it to be very clear that this is a parallel execution: use Task.Run:
_ = Task.Run(() => PerformMyTaskAsync(CancellationToken));

Both _ = PerformMyTaskAsync(CancellationToken); and var task = PerformMyTaskAsync(CancellationToken); are identical, the only difference is that _ (discard) suppresses the warning because it is not awaited if you use PerformMyTaskAsync(CancellationToken);.
You do not need PerformMyTaskAsync(CancellationToken).Start(); to call an asynchronous method. Task is already started when you call the method. If you do not want to store the result ( awaitable task), you can simply use PerformMyTaskAsync(CancellationToken);

Related

Start a concurrent async task from within another async task

I have an I/O-bound task implemented with an async-await function.
At some point in this function, I receive some information which allows me to start a concurrent task, which is also I/O-bound (and so it is also implemented with an async-await function). My original task is not bound by this new task - I just need to set it going in the background.
If I do the following, I get warned that I'm not awaiting the call. I don't want to await the call! I want it to happen in the background!
async Task AnotherAsyncThing()
{
// ...
}
async Task SomeAsyncThing()
{
// ...
// run concurrently - warning raised here
Task.Run(async () => await AnotherAsyncThing());
// ...
}
Am I missing something horribly obvious here? It feels like I am!
You can do something like this:
_ = AnotherAsyncThing()
This is the discards feature added in C# 7.0 and is a way of communicating the fact you're not interested in the return value to the compiler.
Yes and no :)
so often bugs occur when people forget to wait for tasks and it is considered a risk in APIs for instance to keep spinning up non awaited tasks because you can sometimes do so rapidly with bad performing client code and if that can steal many resources ... we'll i'm sure You can imagine.
But to signify that You know what You're doing and assume full responsibility, You can use the TPL like this and get rid of the warnings
_ = Task.Run(
() => _ = AnotherAsyncThing()
);
But each time this code is passed it will continue immediately and start something which will also continue to run. So Say your API gets a post, which accidentally happens every 10th millisecond instead of every 10th second as intended ... there is a danger in making the use of these things a standard.
It is a tool for a specific purpose, not the new white for walls, but yea You may have missed that we now should tell by using the nevermind underscore, that we know what we're doing this time and the compiler should back out from helping.

Async Await and Task.Run issue

I need to know are there any differences in these records and if so, what are they?
It`s quite difficult for me:
1) Task.Run(async () => { await CheckVerification(); });
2) Task.Run(() => CheckVerification());
3) await Task.Run(async () => { await CheckVerification(); });
Maybe it is easier to understand the difference if we forget about Task.Run for a second. The difference between your 1st and 2nd points is basically the same as awaiting or just returning an inner task from a Task returning method:
// 1)
public async Task WithAwait() => await SomeOtherTaskReturningMethod();
// 2)
public Task WithoutAwait() => return SomeOtherTaskReturningMethod();
The first one creates another task, which wraps the inner one, which is a small overhead but otherwise these two methods are functionally almost identical. A small difference is when SomeOtherTaskReturningMethod throws an exception, then the inner task's AggregatedException will be unwrapped, and the (first) inner exception will be thrown further. Of course, things still depend on what happens to the external task. In your 3rd point it is also awaited so you will get the unwrapped exception from the outer task (if any), while the 1st and 2nd examples are just fire and forget.
Now let's consider Task.Run again. The main question why does this method have overloads, which accept Tasks (actually Task returning callbacks), when you can also simply call await CheckVerification(); and get the same result? (I know it was not part of the question but it may worth to clarify this)
So the reason of such Task.Run overloads exist is that a Task returning method itself is not necessarily executed on another thread (I suggest this reading). For example, it can just send a message through a network socket and returning a Task, which will be completed when a specific answer is received. This makes the operation async, still not multi-threaded.
If you have such a task and you want force it to be executed on another thread, then you can execute it by Task.Run, which uses the default scheduler and executes your task on a pool thread eventually.
It is worth to mention though, that this is quite a rare scenario. In most cases you should rely on the internal implementation of the Task returning methods.
TL;DR:
So I think the real question is whether
await CheckVerification();
or
await Task.Run(() => CheckVerification());
is the better solution (or maybe one of them without await, which is fire and forget mode). In most cases I would vote for the first one but if you are really confident that the task returned by CheckVerification must be assigned to a pool thread (regardless whether it does that inside or not), then the second option also can be justified.
1) Starts a task. That task will wait for the method within, but asynchronously, so your UI or calling thread won't block.
2) Starts a task, which starts another task. Everything runs asynchonously, nothing gets awaited, completely fire and forget.
3) Will start a task, that task starts a method and awaits it, giving back execution context, letting the calling thread give away the execution context with its await, letting the method calling this continue execution until it comes to awaiting this method.

C# Asynchronous call "invoke and forget"

In c# when you invoke the await method inside an async method, the code will be executed from the calling context to that method. What if I want to make an asynchronous call which will just continue from the same line of code directly (even if the asynchronous action did not finish yet) instead of getting back to the calling context? How can I do that?
What if I want to make an asynchronous call which will just continue from the same line of code directly (even if the asynchronous action did not finish yet) instead of getting back to the calling context? How can I do that?
The easiest way, which works whether Something is synchronous or asynchronous:
var _ = Task.Run(() => Something());
But, as Eric Lippert stated:
it is a strange thing to get a task and then not care about what happens when it completes.
Or, as I like to put it: fire-and-forget is almost never what you really want. To "forget" means:
You don't care when it completes.
You don't care whether it completes. E.g., if your app exits (or app pool is recycled if on ASP.NET), then your background work is just lost.
You don't care whether it completes successfully. E.g., if your work throws an exception, you want to silently swallow that exception.
In real-world code, this scenario is extremely rare.
An await is, by definition, a point at which you must asynchronously wait for the task to finish before continuing the workflow. If you don't have to wait, then don't wait! There is no requirement that you await anything.
Your question is rather like asking "I have an IEnumerable<int> but I don't care what integers are in it; do I have to foreach over it?" No, you don't. If you don't care what the result is, you don't have to get a result from a sequence. If you don't care what the result of a task is, you don't have to await it.
But it is a strange thing to get a sequence and then not enumerate it, and it is a strange thing to get a task and then not care about what happens when it completes.
If you want to start the async method and continue inside the function you can do something like Task<string> getStringTask = asyncMethodThatReturnsString();. Then continue until you want to wait for the async task to finish at which point you would call string output = await getStringTask;.

Stop this async function calls, just return simple values instead [duplicate]

This question already has answers here:
C# Task which returns a value
(2 answers)
Closed 6 years ago.
I simply want to return a string from a function where I need to do api calls on windows phone environment. I dont want to return a Task, just a string.
I simply dont know how to get values from functions without always using await at the exact place I call a function that should be simply executed (which makes this entire async/await thing senseless).
Please explain me how I can get something like this:
string TheStringIWant(someParameter)
{
string result = await LoadDataAsync();
return result;
}
Sorry, I'm going to give you the "hard love" answer.
I simply want to return a string from a function where I need to do api calls on windows phone environment. I dont want to return a Task, just a string.
Too bad. The correct solution is to return a Task<string>, especially on a mobile platform. Any other solution is just going to be a hack.
I simply dont know how to get values from functions without always using await at the exact place I call a function that should be simply executed (which makes this entire async/await thing senseless).
It's not senseless at all. async/await is what keeps your UI responsive. This is necessary for your app to be accepted in the Windows Store.
Assuming you are trying to all a function that returns a Task you'd just do this:
var result = LoadDataAsync().GetAwaiter().GetResult();
Of course, this is not forcing the method to run synchronously, rather it is telling the compiler that you want to wait until the asynchronous task completes and then return the results. It is functionally equivalent to
var result = await LoadDataAsync();
All this syntax does is allow you to skip annotating your method with an async keyword. You do need to wait one way or the other. If you are calling a method that runs asynchronously and you need to do something to wait for that function to complete and return the data to you, otherwise you would get bad data.
Just a point of caution, when you make a blocking call on an async method (either by Wait() or .Result) you have the risk of causing a dead lock if the SynchronizationContext of the calling method is not null. Because the async method will attempt to schedule its continuation on the Synchronization Context of the calling method but the calling method blocks on the completion of the async method so you end up in a dead lock.
One way to guarantee no dead lock is to push this async call to a background thread ie. by Task.Run. Background threads do not have SynchronizationContext so no dead lock.
Something like:
var result = Task.Run(async() => await LoadDataAsync()).Result;
ps. You do not need to call Wait() before the Result property. Result will block the thread until task is completed.

How does C# 5.0's async-await feature differ from the TPL?

I don't see the different between C#'s (and VB's) new async features, and .NET 4.0's Task Parallel Library. Take, for example, Eric Lippert's code from here:
async void ArchiveDocuments(List<Url> urls) {
Task archive = null;
for(int i = 0; i < urls.Count; ++i) {
var document = await FetchAsync(urls[i]);
if (archive != null)
await archive;
archive = ArchiveAsync(document);
}
}
It seems that the await keyword is serving two different purposes. The first occurrence (FetchAsync) seems to mean, "If this value is used later in the method and its task isn't finished, wait until it completes before continuing." The second instance (archive) seems to mean, "If this task is not yet finished, wait right now until it completes." If I'm wrong, please correct me.
Couldn't it just as easily be written like this?
void ArchiveDocuments(List<Url> urls) {
for(int i = 0; i < urls.Count; ++i) {
var document = FetchAsync(urls[i]); // removed await
if (archive != null)
archive.Wait(); // changed to .Wait()
archive = ArchiveAsync(document.Result); // added .Result
}
}
I've replaced the first await with a Task.Result where the value is actually needed, and the second await with Task.Wait(), where the wait is actually occurring. The functionality is (1) already implemented, and (2) much closer semantically to what is actually happening in the code.
I do realize that an async method is rewritten as a state machine, similar to iterators, but I also don't see what benefits that brings. Any code that requires another thread to operate (such as downloading) will still require another thread, and any code that doesn't (such as reading from a file) could still utilize the TPL to work with only a single thread.
I'm obviously missing something huge here; can anybody help me understand this a little better?
I think the misunderstanding arises here:
It seems that the await keyword is serving two different purposes. The first occurrence (FetchAsync) seems to mean, "If this value is used later in the method and its task isn't finished, wait until it completes before continuing." The second instance (archive) seems to mean, "If this task is not yet finished, wait right now until it completes." If I'm wrong, please correct me.
This is actually completely incorrect. Both of these have the same meaning.
In your first case:
var document = await FetchAsync(urls[i]);
What happens here, is that the runtime says "Start calling FetchAsync, then return the current execution point to the thread calling this method." There is no "waiting" here - instead, execution returns to the calling synchronization context, and things keep churning. At some point in the future, FetchAsync's Task will complete, and at that point, this code will resume on the calling thread's synchronization context, and the next statement (assigning the document variable) will occur.
Execution will then continue until the second await call - at which time, the same thing will happen - if the Task<T> (archive) isn't complete, execution will be released to the calling context - otherwise, the archive will be set.
In the second case, things are very different - here, you're explicitly blocking, which means that the calling synchronization context will never get a chance to execute any code until your entire method completes. Granted, there is still asynchrony, but the asynchrony is completely contained within this block of code - no code outside of this pasted code will happen on this thread until all of your code completes.
Anders boiled it down to a very succinct answer in the Channel 9 Live interview he did. I highly recommend it
The new Async and await keywords allow you to orchestrate concurrency in your applications. They don't actually introduce any concurrency in to your application.
TPL and more specifically Task is one way you can use to actually perform operations concurrently. The new async and await keyword allow you to compose these concurrent operations in a "synchronous" or "linear" fashion.
So you can still write a linear flow of control in your programs while the actual computing may or may not happen concurrently. When computation does happen concurrently, await and async allow you to compose these operations.
There is a huge difference:
Wait() blocks, await does not block. If you run the async version of ArchiveDocuments() on your GUI thread, the GUI will stay responsive while the fetching and archiving operations are running.
If you use the TPL version with Wait(), your GUI will be blocked.
Note that async manages to do this without introducing any threads - at the point of the await, control is simply returned to the message loop. Once the task being waited for has completed, the remainder of the method (continuation) is enqueued on the message loop and the GUI thread will continue running ArchiveDocuments where it left off.
The ability to turn the program flow of control into a state machine is what makes these new keywords intresting. Think of it as yielding control, rather than values.
Check out this Channel 9 video of Anders talking about the new feature.
The problem here is that the signature of ArchiveDocuments is misleading. It has an explicit return of void but really the return is Task. To me void implies synchronous as there is no way to "wait" for it to finish. Consider the alternate signature of the function.
async Task ArchiveDocuments(List<Url> urls) {
...
}
To me when it's written this way the difference is much more obvious. The ArchiveDocuments function is not one that completes synchronously but will finish later.
The await keyword does not introduce concurrency. It is like the yield keyword, it tells the compiler to restructure your code into lambda controlled by a state machine.
To see what await code would look like without 'await' see this excellent link: http://blogs.msdn.com/b/windowsappdev/archive/2012/04/24/diving-deep-with-winrt-and-await.aspx
The call to FetchAsync() will still block until it completes (unless a statement within calls await?) The key is that control is returned to the caller (because the ArchiveDocuments method itself is declared as async). So the caller can happily continue processing UI logic, respond to events, etc.
When FetchAsync() completes, it interrupts the caller to finish the loop. It hits ArchiveAsync() and blocks, but ArchiveAsync() probably just creates a new task, starts it, and returns the task. This allows the second loop to begin, while the task is processing.
The second loop hits FetchAsync() and blocks, returning control to the caller. When FetchAsync() completes, it again interrupts the caller to continue processing. It then hits await archive, which returns control to the caller until the Task created in loop 1 completes. Once that task is complete, the caller is again interrupted, and the second loop calls ArchiveAsync(), which gets a started task and begins loop 3, repeat ad nauseum.
The key is returning control to the caller while the heavy lifters are executing.

Categories