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.
Related
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.
This question already has answers here:
Async lock not allowed
(2 answers)
Closed 5 years ago.
What I mean is, say we have an async method Task<string> CalculateSha256(string s). Is it possible, that calls from thread #1 and thread #2 are executed consecutively as oposed to being executed concurrently, without threads #1 and #2 knowing anything about each other? For example, I have a controller,
public async Task<string> Get(string value)
{
return await CalculateSha256(value);
}
and I want two different requests to access the chunk of code that's responsible for calculation (CalculateSha256) consecutively.
You need to synchronize the access to CalculateSha256 method that only one thread will execute it at a time.
Since lock statement does not play nicely with async you can use SemaphoreSlim class.
Just add it as a static field to your controller:
private static readonly SemaphoreSlim _semaphoreSlim = new SemaphoreSlim(1, 1);
And use WaitAsync method in your action (and do not forget to release it when you finish, using finally block):
public async Task<string> Get(string value)
{
await _semaphoreSlim.WaitAsync();
try
{
return await CalculateSha256(value);
}
finally
{
_semaphoreSlim.Release();
}
}
If you find this approach useful and you do not like to reapeat the try finally block you can create a base controller class with a protected generic helper:
protected async Task<T> GetConsecutively(Func<Task<T>> taskFactory)
{
await _semaphoreSlim.WaitAsync();
try
{
return await taskFactory();
}
finally
{
_semaphoreSlim.Release();
}
}
And modify Get method to pass a lambda expression to it:
public async Task<string> Get(string value)
{
return await GetConsecutively(() => CalculateSha256(value));
}
Or alternatively use Stephen Cleary's AsyncLock instead of SemaphoreSlim which supports a high level API closer to the lock statement:
private static readonly AsyncLock _asyncLock = new AsyncLock();
public async Task<string> Get(string value)
{
//Notice the use of using block
//instead of try and finally
using(await _asyncLock.LockAsync())
{
return await CalculateSha256(value);
}
}
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.
I am having a difficult time calling an async method from my current method.
Trying to do something like this:
int i;
public void Method1() {
while (statement1) {
~code~
Method2(i);
}
while (statement2) {
~code~
Method2(i);
}
}
public async void Method2(int i) {
if(statement){
~code~
await Task.Delay(2000);
}
else
{
~code~
await Task.Delay(2000);
}
}
So i want basically Method2 to be a method for controlling the flow (uses another method which changes pictures in pictureboxes), but I can't get it to work and when it works it never delays anything. Does anyone knows what I am doing wrong?
Method2 changes Method1's while statements eventually.
The best practice for async/await is to use async "all the way down" (unless you really and truly don't care about Method1 waiting for Method2 to complete).
It's possible to mix Task.Wait (or similar constructs) with async code, but it's a bad idea because it can lead to deadlocks.
The best thing here would be, as others have indicated, just make Method1 async too:
public async Task Method1() {
while (statement1) {
await Method2(i);
// ...
}
Note that you'll have to make Method1 return a Task too because otherwise you can't wait it:
public async Task Method2
This may be a case of the XY Problem though because there's no reason for the code sample you provide to be async in the first place (or even a separate method, for that matter) - you can just do Thread.Sleep instead. Also, the "if" statement is pointless because, based on what you've shown us, you delay for 2 seconds either way. It would be helpful if you could show a more substantial code sample so we can get a better sense of what you're trying to do so we can recommend whether async is even an appropriate solution here.
One final point: one of the purposes of async/await is to allow the calling thread to do other work while it's waiting for a result - for example, if you want to download a file without "hanging" the UI. I've seen plenty of cases where people use async/await in a way that essentially obviates the purpose though. For example:
static void Main(string[] args) {
// This is a terrible thing to do but it's for illustration purposes
Task task = Method1();
task.Wait();
// Some other work
}
private static async Task Method1() {
await Method2();
// Some other work
}
private static async Task Method2() {
await Method3();
// Some other work
}
private static async Task Method3() {
await Task.Delay(1000);
}
This is a pretty dumb illustration, granted, but in this case the async/await is completely pointless because it's just doing each action sequentially anyway.
For another method to be able to await Method2 the latter must return have a return type of Task or Task (and not void):
public async Task Method2(int i) {
if(statement){
~code~
await Task.Delay(2000);
}
else
{
~code~
await Task.Delay(2000);
}
Method1 should then be marked as async and await Method2:
public async void Method1() {
while (statement1) {
~code~
await Method2(i);
}
while (statement2) {
~code~
await Method2(i);
}
}
You should make Method1 also asyncronous and add await operator for Method2 call:
public async Task Method1() {
while (statement1) {
~code~
await Method2(i);
}
while (statement2) {
~code~
await Method2(i);
}
}
public async Task Method2(int i) {
if(statement){
~code~
await Task.Delay(2000);
}
else
{
~code~
await Task.Delay(2000);
}
}
If you need Method1 to be syncronous for some reason, you should call Wait() on task returned from Method2. However it's considered as bad practice because you loose advantage of .NET thread pool.
This question already has answers here:
Can constructors be async?
(15 answers)
Closed 1 year ago.
I have a question regardin the async method which I call in constructor and how to solve or is there a good work around, here is an example
public Constructor()
{
Value = PopulateValueFromDB(); //async method
CalculateInDB(); // async method
}
public async Task<string> PopulateValueFromDB()
{
... do some async calls
return await ...
}
public async Task CalculateInDB()
{
...
return await ...
}
Basically in constructor i have an error, because i cannot use await there, and i cannot make it async.
For CalculateInDB i can make return it void, then i solve the issue with it, although i read somewhere that returning void is not very good solution.
Regarding the PopulateVlaue method ...i have to return something ...
So is there a work around ir i shouldn't use those methods then and make them sync instead of async?
I have a blog post on async constructors that covers a variety of approaches. If possible, I recommend you use the factory pattern, as such:
private Constructor()
{
}
private async Task InitializeAsync()
{
Value = await PopulateValueFromDBAsync();
await CalculateInDBAsync();
}
public static async Task<Constructor> Create()
{
var ret = new Constructor();
await ret.InitializeAsync();
return ret;
}
This is a time to use old tech!
ThreadPool.QueueUserWorkItem.
Cheers -