Non-Async Method In Async Call Stack [duplicate] - c#

This question already has answers here:
Why use async and return await, when you can return Task<T> directly?
(9 answers)
Closed 5 years ago.
Sorry for a terrible title, I just wanted to confirm that I am making the correct assumptions.
Say I have 3 methods that are simplified to:
public async Task Method1()
{
var obj = await Method2();
//do work on obj
}
public Task<object> Method2()
{
//do some work
return Method3();
}
public async Task<object> Method3()
{
//do async work
return obj;
}
Method2 above does no async work internally, but is in my async stack. It could be rewritten as:
public async Task<object> Method2()
{
//do some work
return await Method3();
}
Am I correct that, as Method2 doesn't actually do async work, that it is better to leave it as a non-async method? My thought is that I'm saving the overhead of creating an extra state machine to hold the thread's resources when it is not needed.

Correct. You can return the Task directly from a method without adding the async/await keywords if the method does not need to await any result (ie. consume the result of a task or wait for a task to complete to be able to do some execution). That returned Task can then be awaited by a caller further down the call stack. This can save a little overhead and make for slightly less code (although that amount of code is actually trivial).
You often see this with pass through or convenience methods.

Related

Using async in a method in a chain [duplicate]

This question already has answers here:
Why use async and return await, when you can return Task<T> directly?
(9 answers)
Closed 2 years ago.
static async Task Main(string[] args)
{
var txt = await GetTask();
}
static Task<string> GetTask()
{
return GetText();
}
static async Task<string> GetText()
{
await Task.Delay(2000);
return "result";
}
Is asynchrony breaking in my case?
Do I need to make the GetTask async method?
If it's a simple forward, no you don't, if there is a chance something in the code block could go wrong, you would have to handle exceptions with Task.FromException to push the exception onto the task (in the way the async and await pattern would), in which case it's probably easier to just use the async keyword and await the awaitables for a small performance hit of the IAsyncStateMachine.

How do you handle a 3rd party interface returning Task if you don't have any async code? [duplicate]

This question already has answers here:
How to implement interface method that returns Task<T>?
(4 answers)
Closed 6 years ago.
I am working with a third-party dll which exposes methods which return Task and Task<T>. I don't have any control over this assembly or the interface, and I assume the author assumed everything would need to be async since the naming of the methods are *Async() as shown below.
Given that, how do I properly implement the interface if I don't actually have any asynchronous code running?
public interface IFoo
{
Task DoWorkAsync();
Task<int> GetValueAsync();
}
My attempt was the following:
public class FooBar : IFoo
{
public async Task DoWorkAsync()
{
// Do Some Work
await Task.Yield();
}
public async Task<int> GetValueAsync()
{
// Do Some Work
var result = ...;
return Task.FromResult(result);
}
}
Additionally:
Was the author correct in exposing only methods that returned Task/Task<T>?
Was the author correct in suffixing method names with *Async()? Code analysis doesn't complain if I write an async method without appending Async to the name.
If you don't have async work to do don't include the async keyword. Your GetValueAsnyc function was almost correct, you just needed to drop the async. For your DoWorkAsync you should just not mark the method async and return a completed task.
public class FooBar : IFoo
{
public Task DoWorkAsync()
{
// Do Some Work
//If you can use .NET 4.6
return Task.CompletedTask;
//For older versions, the thing you pass in does not matter, I like to use bool.
return Task.FromResult(false);
}
public Task<int> GetValueAsync()
{
// Do Some Work
var result = ...;
return Task.FromResult(result);
}
}
However, if your code is slow and you end up blocking the UI for a long period of time I would consider looking in to if you can re-write your code as actually being async or perhaps wrapping the code in to a background thread, but I would only do a background thread if it was a last resort.

Converting synchrous to asynchrous method in C#

I have gone through several post for converting existing synchronous method to asynchronous. So based on what I have read I am converting the synchronous method to asynchronous like below
Synchronous
public class SomeClass
{
public int DoWork()
{
return DoLongRunningWork();
}
public int DoLongRunningWork()
{
Thread.Sleep(1000);
return 1;
}
}
I converted this to Asynchronous version like below
public class SomeClass
{
public async Task<int> DoWorkAsync()
{
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
return await DoLongRunningWorkAsync();
}
public Task<int> DoLongRunningWorkAsync()
{
Thread.Sleep(1000);
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
return Task.Run(() => 1);
}
}
I am calling this from Main() Method
static void Main()
{
Someclass worker = new SomeClass();
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
var result = worker.DoWorkAsync().GetAwaiter().GetResult();
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
Console.WriteLine(result);
Console.ReadKey();
}
Is this a correct way to convert synchronous to asynchronous method?
I was expecting Main method's ManagedThreadId will be different than DoWorkAsync and DoLongRunningWorkAsync method's ManagedThreadId. But they are same, why?
I used Thread.Sleep() just to simulate the long running method. As per the suggestions below i should have used Task.Delay() to avoid any confusion.
I dont think i have to put my actual business logic here to understand the concept of async.
As per Stephen Cleary
1> Identify the naturally-asynchronous operations your code is doing.
2>Change the lowest-level API calls to invoke asynchronous APIs (with await) instead of synchronous APIs.
However none of the .Net Libarary methods im using inside LongRunningMethod are naturally-asynchronous or awaitable and also LongRunningMethod is not doing any I/O operation.
Requirement
I have Web API which takes JSON string as input. The JSON needs to be transformed into some C# object. For transformation I am building a C# library which takes JSON string as input and then Transform that JSON string into C# objects based on some rules. The library may take time ( few milliseconds) for Transformation, during this I DO NOT want Web API's main thread to block. The main thread should be free to take any other request while the transformation is going on background thread (some other thread).
public class MyWebApi: ApiController
{
private ILib _myLibrary
public MyWebApi(ILib myLibrary)
{
_myLibrary = myLibrary
}
publi async Task<SomeObject> Transform(string jsonString)
{
// i want to make LongRunningMethod() method awaitable
// or at least it needs to execute on different thread so that
// main thread will be free.
var result = await _myLibrary.LongRunningMethod(jsonString);
return result;
}
}
publi class MyLibrary:ILib
{
// A method that does Transformation
public async Task<SomeObject> LongRunningMethod(string jsonString)
{
var result = new SomeObject();
// parse jsonString here
// and based on some complex rules create SomeObject
// this operation may takes time (lets say few milliseconds)
// i may call some other private methods here or public methods from other library
return result
}
}
based on what I have read I am converting the synchronous method to asynchronous like below
The best way to convert synchronous methods to asynchronous (as I describe in my async brownfield article) is the following:
Identify the naturally-asynchronous operations your code is doing. This is anything that is not running CPU code, e.g., I/O.
Change the lowest-level API calls to invoke asynchronous APIs (with await) instead of synchronous APIs.
Note the compiler warning and change your calling method to be async with a proper (Task/Task<T>) return type. Also add an Async suffix.
Change calling methods to use await, and repeat step (3).
When you run into problems with step (3), check out my articles on async OOP, async MVVM (if applicable), and async brownfield.
Applying these to your code:
Identify the naturally-asynchronous operations your code is doing. This is anything that is not running CPU code, e.g., I/O.
Your lowest-level method has a call to Thread.Sleep, which is not running code. The asynchronous equivalent is Task.Delay.
Change the lowest-level API calls to invoke asynchronous APIs (with await) instead of synchronous APIs.
public int DoLongRunningWork()
{
await Task.Delay(1000);
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
return 1;
}
Note the compiler warning and change your calling method to be async with a proper (Task/Task<T>) return type. Also add an Async suffix.
public async Task<int> DoLongRunningWorkAsync()
{
await Task.Delay(1000);
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
return 1;
}
Change calling methods to use await, and repeat step (3).
public int DoWork()
{
return await DoLongRunningWorkAsync();
}
Note the compiler warning and change your calling method to be async with a proper (Task/Task<T>) return type. Also add an Async suffix.
public async Task<int> DoWorkAsync()
{
return await DoLongRunningWorkAsync();
}
Change calling methods to use await, and repeat step (3).
In this case, since Main cannot be async, you'll need to block with GetAwaiter().GetResult(), just like you currently have.
Final result:
public async Task<int> DoWorkAsync()
{
return await DoLongRunningWorkAsync();
}
public async Task<int> DoLongRunningWorkAsync()
{
await Task.Delay(1000);
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
return 1;
}
I was expecting Main method's ManagedThreadId will be different than DoWorkAsync and DoLongRunningWorkAsync method's ManagedThreadId. But they are same, why?
"Asynchronous" does NOT mean "runs on a different thread." See my async intro for more details about how async/await works.

Nested Task<T> calls without async/await

This is kind of related to the following post: Why use Async/await all the way down
I am curious what happens in the following scenario:
Updated due to comment:
async Task FooAsync()
{
await Func1();
// do other stuff
}
Task Func1()
{
return Func2();
}
async Task Func2()
{
await tcpClient.SendAsync();
// do other stuff
}
Does this whole process becomes a blocking call? Or because Func1() is actually awaited on, the UI can go and work on something else? Ultimately is it necessary to add the async/await on Func1()? I've played around with it but I don't actually notice any difference, hence the question. Any insight would be great, thanks!
Async and await are just compiler features.
Without await calling async method will cause it to execute synchronous (blocking) way..
When you are writing await all code bellow await is wrapped in Task.ContinueWith() Method by compiler automaticly, this means that when task is finished code below is executed later
public async Task<int> method2(){
return Task.FromResult(1);
}
public void method1(){
await method2()
Console.WriteLine("Done");
}
will translate something like :
public Task<int> method2(){
return Task.FromResult(1);
}
public void method1(){
method2().ContinueWith(x => {
Console.WriteLine("Done");
});
}
The only problem of not making Func1 and async method and not awaiting Func2 in it is that any thrown exception won't show Func1.
The bottom line is that await works on awaitables and Task/Task<T> are awaitables.

Non async method returning Task<> [duplicate]

This question already has answers here:
Why use async and return await, when you can return Task<T> directly?
(9 answers)
Closed 7 years ago.
I would like to know if there is a difference between these two async patterns. Obviously they will work. I would like to know if there is a hidden trap or performance overhead. What will happen with aggregateexception call stack in both cases?
//------Pattern1-------- PassThruMethod is awaiting
public async void EventHandler()
{
await PassThruMethod();
}
public async Task<int> PassThruMethod()
{
return await MyAsyncMethod();
}
public Task<int> MyAsyncMethod()
{
return Task.Run(() => 1);
}
//---Pattern2----- PassThruMethod is not awaiting
public async void EventHandler()
{
await PassThruMethod();
}
public Task<int> PassThruMethod()
{
return MyAsyncMethod();
}
public Task<int> MyAsyncMethod()
{
return Task.Run(() => 1);
}
There's no need to use async if you don't use await - since your PassThruMethod doesn't need await, don't use it. You can change it at any time if you eventually find out it's not good enough.
Using await does have some overhead (not exactly huge, but there is some), so for a case like this, there's no reason to use it. Returning Task is just fine.

Categories