0

I googled a lot and for the moment the only async implementation I found (including MSDN site) is the following:

public async void Foo()
{
...
 await StreamReader.ReadAsync();
...
}

So in all the cases they use some method which is already async. And this is not what I need.

Let's say that I have a heavy method that does something:

public void DoSomthing()
{
...
}

And there is method where I call this DoSomething:

public void MajorMethod()
{
  DoSomething();
}

I want to make DoSomething ayncthonous and call it.

The only solution I see would be the following one:

public Task MajorMethod()
{
  return Task.Run(()=>DoSomething());
}

But I read some comments that it's not really the async. So how can I make DoSomething async?

J.Doe
  • 155
  • 2
  • 7

2 Answers2

0

If the MajorMethod has no other things to do other than calling the DoSomething, your code is fine. But if you need to do other stuff after calling to DoSomething, then mark MajorMethod as async, and use await before Task.Run

public async Task MajorMethod()
{
    await Task.Run(()=>DoSomething());

    //stuff in here will executed after DoSomething completed
}

Examples from MSDN: Asynchronous programming

or just google c# async

Evan Huang
  • 1,245
  • 9
  • 16
  • 5
    While I wouldn't say this is a no-op compared with the OP's existing implementation, the differences are pretty subtle - and normally, I'd recommend using the OP's code instead. What do you think the benefits are of starting a task and then asynchronously awaiting it rather than just returning the started task directly? – Jon Skeet Dec 11 '17 at 08:11
  • @JonSkeet You are right. I misunderstanding OP's need. Was assuming some action will be performed after calling the `DoSomething` in the `MajorMethod`. No need to use `await` if the `MajorMethod` is returned right after the call – Evan Huang Dec 11 '17 at 08:19
0

You should be clear about the role async/await play in the Task Asynchronous Pattern. Making an async method does not parform an operation asynchronously just like that. Marking an existing method async will not magically perform everything in there asynchronously. Its main effect is that now you are allowed to use await within the method (I read that it even was discussed if the async keyword was necessary at all; it was added to avoid a breaking change when a local variable in existing methods would be named await).

await also does not provide asynchrony by itself, it provides a way to synchronize to another asnychronous method and yield while the other operation is still running. You can await another async method, but unless somwhere down the chain there is an actual Task running in another thread, the async method might even return synchronously.

In consequence this means that you need an operation that runs asynchronously first (such as a DB query, file access, network communication) and from there you create a chain of async methods that await the previous method.

Now in your case, when you have a computationally intensive method that does not wait for external resources, you can choose to perform the operation asynchronously. Since modern CPUs usually have more than one core at your disposal, you can increase both, performance and application responsiveness like that. The method would not be async, since it does not await anything:

void DoSomething()
{
    //...
}

Task DoSomethingAsync() {
    return Task.Run(DoSomething);
}

All callers of DoSomethingAsync can now use await to synchronize with this operation running in the background (note the change in return type to Task to allow callers to await):

async Task MajorMethod() {
    //...
    await DoSomethingAsync();
    //...
}

This would allow callers of MajorMethod to synchronize with it. What you can also do is to do stuff in MajorMethod while DoSomethingAsync is running (and still await to allow callers to do even more parallel operations):

async Task MajorMethod() {
    //This part will run before DoSomethingAsync
    //...
    Task doSomethingTask = DoSomethingAsync();
    //This part is executed at the same time as DoSomethingAsync
    //...
    await doSomethingTask; //Here the caller can do more operations while DoSomething is running
    //This part will be executed after DoSomethingAsync has finished
    //...
}

This form of acquiring a task, doing something and only then awaiting the task has to be done somewhere in the chain, otherwise you have no benefit from the asynchronous operation. Even though this might be an overgeneralization, since synchronization can happen in more subtle ways, for example with a custom synchronization context. But as far as your question is concerned, you should go with: There is an actual task on one end and something that is done after the async call, but before the await on the other end.

Sefe
  • 13,731
  • 5
  • 42
  • 55