Abusing async/await?

First I see code like this:
public async Task MyMethodAsync()
{
    await Task.Run(sometask);
}

Open in new window

And I think that's silly, because there's no code after the await, so why bother?

But then I saw there's a Unit Test:
await xyzzy.MyMethodAsync();
...
more code

Open in new window

and for a moment it looks like maybe this does need to be async.

Is there any benefit to awaiting a Task.Run() operation?

Then to get even more obscure, I find that sometask is actually sometaskAsync:
pubic async Task sometaskAsync()
{
    Task<TOutput> task = await Task.Factory.FromAsync(something.BeginInvoke(Input,null,null), something.EndInvoke);

    if (task.IsFaulted)
    {
    ...
    }
    ...
}

Open in new window

so the whole code now is:
[System.Diagnostics.CodeAnalysis.SuppressMessage("Await.Warning", "CS4014:AwaitWarning", Justification = "Don't need to wait for the function to finish.")]
public void StartSomething()
{
    MyMethodAsync();
}

public async Task MyMethodAsync()
{
    await Task.Run(sometaskAsync);
}

pubic async Task sometaskAsync()
{
    Task<TOutput> task = await Task.Factory.FromAsync(something.BeginInvoke(Input,null,null), something.EndInvoke);

    if (task.IsFaulted)
    {
    ...
    }
    ...
}

Open in new window

and the compiler gives a complaint about StartSomething() calling MyMethodAsync() without awaiting it, and that error message is suppressed by adding the Suppress Warning.

Now my mind is just boggled.

It looks like:
1. StartSomething() calls MyMethodAsync()
2. MyMethodAsync() executes Task.Run(sometaskAsync), and sets up a note to return here when, umm, when the Task.Run() finishes starting the task?
3. MyMethodAsync() returns to StartSomething(), which returns to it's caller (probably a button click event handler).
4. The Task.Run() in MyMethodAsync() finishes starting the task, and signals an interrupt to the operating system notifying it that it has returned.
5. The operating system grabs a thread from the thread pool and tells it to jump to the await Task.Run(...) and begin executing the code after the await.
6. There is no code after the await, so that thread just returns and goes back to the thread pool.

7. We have Task.Run(sometaskAsync) starting sometaskAsync().
8. sometaskAsync() in turn starts a task using Task.Factory.FromAsync(...), which I'm not familiar with, and sets up a callback to return when, umm, I'm a little unclear here exactly what we are awaiting for.
9. sometaskAsync() returns with a note to go back and resume whenever Task.Factory.FromAsync(...) says it's time.
10. sometaskAsync() returns to, nothing, because it was started with Task.Run().
At this point I'm not clear what happens to the thread running sometaskAsync() that was started with Task.Run(). This is starting to boggle my mind.
11. At some point, Task.Factory.FromAsync(...) says it's time, the operating system is notified, a thread from the thread pool is allocated to resume execution after the await Task.Factory.FromAsync(...), where we test the status of the task:
if (task.IsFaulted)
{
...

Open in new window

And somewhere along the line, there's a something.BeginInvoke(...), which I'm not sure what that is, followed by something.EndInvoke, which I'm also not sure what that is.

So my question is, does this all make sense? Or is this an abuse of async/await?
deleydAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

it_saigeDeveloperCommented:
An await, in the most basic terms, is nothing more that a promise that *something* will be returned.  So in that aspect, you are basically correct, a separate thread is created to process the waited method.  However, when something is *await*-ed, the thread that called the await is blocked until the results are returned.  When the results are returned, the blocked thread continues processing.

See if this sample program doesn't clear some of your confusion:
using System;
using System.Threading.Tasks;

namespace EE_Q29074254
{
    class Program
    {
        static void Main(string[] args)
        {
            var task = new Task(ProcessLinesAsync);
            task.Start();
            task.Wait();
            Console.WriteLine("This line appears before all of the results are processed");
            while (task.Status == TaskStatus.Running) { ;}
            Console.ReadLine();
        }

        static async void ProcessLinesAsync()
        {
            Console.WriteLine("Testing an awaited result");
            Task task = new Task(HaveSomeFun);
            task.Start();
            task.Wait();
            int x = await ProcessLines();
            Console.WriteLine($"Processed {x} lines");
            Console.WriteLine("This line appears after the results are processed.");
            Console.WriteLine("Finished processing the task.  Press any key to exit.");
        }

        static async Task<int> ProcessLines()
        {
            int count = 0;
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine($"Processing line {i}...");
                await Task.Delay(500);
                count++;
            }
            return count;
        }

        static async void HaveSomeFun()
        {
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine($"Where's Waldo?  Checking position = {i}");
                await Task.Delay(250);
            }
        }
    }
}

Open in new window

Which produces the following results -Capture.PNG
-saige-
0
käµfm³d 👽Commented:
a separate thread is created to process the waited method.
That *may be* true for Task.Run, but async/await itself does not create a new thread.

the thread that called the await is blocked until the results are returned.
Er, yes and no. The thread is blocked in the sense that a continuation is scheduled, but the thread itself is not actually blocked. The continuation is resumed when the task completes. We usually use async/await to await an asynchronous result from some I/O device. In such cases, the continuation fires after the I/O completion port receives a message that I/O is completed.
0
käµfm³d 👽Commented:
To me, this looks like fake asynchronicity...but it's difficult to tell since we can't see the details of that innermost code. Task.Run is used for work that is CPU-bound, not I/O bound. Looking for Marseinne primes would be CPU-bound; downloading a list of funny Tweets would be I/O-bound. The former can be executed with Task.Run; the latter would use async APIs defined by whatever class you use to download with (and at a lower level use the I/O completion ports that I mentioned above).

That attribute usage is a bit worrisome for me. It smells of someone not understanding how async/await works.

The BeginInvoke/EndInvoke stuff is how we did async/await before C# got the async/await keywords. You can still code in that style if you prefer, but MS introduced async/await because people found the older style to be difficult to manage. Its usage here appears to be under the guise of code that already existed in the older style that is getting wrapped into the new task-based style...which in and of itself is of no worry.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
deleydAuthor Commented:
Thank you everyone for the explanations. I like the term "Fake Asynchronous".
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
.NET Programming

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.