derodevil derodevil - 2 months ago 18
C# Question

Which is the proper way for async method returns task?

I am so confused with the following methods. Which one is the best and why? These are working fine.

public string GetString(int i)
{
return "Testing number " + i.ToString();
}

//async methods where I'm confused with
public Task<string> GetStringAsync(int i)
{
return Task.FromResult<string>(GetString(i));
}
//Or
public Task<string> GetStringAsync(int i)
{
Task<string> task = new Task<string>(() => GetString(i));
task.Start();
return task;
}
//Or
public Task<string> GetStringAsync(int i)
{
var tcs = new TaskCompletionSource<string>();
tcs.SetResult(GetString(i));
return tcs.Task;
}


The caller will be

Task<string> task = SomeClass.GetStringAsync(9);
Console.WriteLine(task.Result);
//Or
var result = await SomeClass.GetStringAsync(9);
Console.WriteLine(result);


Thank you so much.

Answer

I think you may not fully understand why anyone would want to use async. Async .Net allows the freeing up of threads that would normally be waiting on some external action to take place (network call or hard disk call). Normally windows uses I/O Completion Ports for these calls and has recently added async/await keywords to allow .Net access to native asynchronous calls. That being said there is a little overhead when using async as the runtime has to create a state-machine to keep track of a threads current state before assigning the await'd thread a new task.

Thus any async tasks that aren't using a I/O Completion Port are most likely doing more harm than good.

//async methods where I'm confused with
public Task<string> GetStringAsync(int i)
{
    return Task.FromResult<string>(GetString(i));
}

Well let me correctly code this into an async method:

//async methods where I'm confused with
public asyncTask<string> GetStringAsync(int i)
{
    return await Task.FromResult<string>(GetString(i));
}

Still bad, because there is no reason to use async; unless I'm mistaken about how Task.FromResult() works, this has additional overhead for no benefit.

I'm just going to rewrite them all as async and then give my understanding of what affect they have.

public async Task<string> GetStringAsync(int i)
{
    Task<string> task = new Task<string>(() => GetString(i));
    await task.Start();
    return task;
}

It's extremely rare that you should be creating and starting your own tasks, it's not a good idea.

public Task<string> GetStringAsync(int i)
{
    var tcs = new TaskCompletionSource<string>();
    tcs.SetResult(GetString(i));
    return tcs.Task;
}

The TaskCompletionSource was primarily designed to wrap current asynchronous into the async/await pattern. Since this isn't wrapping any type of asynchronous action there is no performance benefit.

public string GetString(int i)
{
    return "Testing number " + i.ToString();
}

This is your best bet. Don't use async/await unless you actually need to.

Stephen Cleary has a great set of Posts that talk about Tasks and Async, I highly recommend you read through it before diving into Async in .Net.

Comments