Overriding an async method not adding async to method signature - c#

I wonder why when I use visual studio to override RemoveLoginAsync()
it looks like this:
public override Task<IdentityResult> RemoveLoginAsync(string userId, UserLoginInfo login)
And not like:
public override async Task<IdentityResult> RemoveLoginAsync(string userId, UserLoginInfo login)
Shouldn't it be an awaitable Task using async?

Shouldn't it be an awaitable Task using async?
A Task is an awaitable. It implements the GetAwaiter pattern. Marking a method with async is simply a flag to the compiler which tells it to transform this method call to a state-machine. But, not all Task returning methods need to be marked as async. For example:
public Task DoSomethingAsync()
{
Console.WriteLine("Oh yay!");
return Task.CompletedTask;
}
In this example, I "faked" an asynchronous operation by returning Task.CompletedTask, I didn't actually need to await anything.
Another, more realistic example:
public Task SendWebRequestAsync()
{
var httpClient = new HttpClient();
return httpClient.GetAsync("http://www.google.com");
}
When I'm returning a Task rather than awaiting it, I'm deferring the awaiting on the task to the method higher up the callstack. This means that I don't allocate a state-machine and I'm also changing a bit the way the exception handling will work here. But, since this is a "tail async call", I don't have to await the operation and hence there's no need for the async modifier.

Related

Call chain for async/await ... await the awaitable or return the awaitable?

Given an async method:
public async Task<int> InnerAsync()
{
await Task.Delay(1000);
return 123;
}
And calling it through an intermediate method, should the intermediate method await the async method IntermediateA or merely return the Task IntermediateB?
public async Task<int> IntermediateA()
{
return await InnerAsync();
}
private Task<int> IntermediateB()
{
return InnerAsync();
}
As best I can tell with the debugger, both appear to work exactly the same, but it seems to me that IntermediateB should perform better by avoiding one more await entry in the state machine.
Is that right?
There is subtle differences in this two approaches. If you await failed task the exception will thrown in that method, but if you pass the task thought that method and then await it, the exception will be thrown in the consumer method. Another difference is more rare, in case of consumer awaiting the task and if it occurred with delay, the task can be finished at the await point and bypass the state machine.

Async Method in SignalR OnConnected()

I have the following:
public override Task OnConnected() {
HandleConnectionAsync(Context).Wait();
return base.OnConnected();
}
In following the guidance around "don't block a hub method", I'm trying to await my HandleConnectionAsync call, but if I use async, I end up with the following:
public override async Task OnConnected() {
await HandleConnectionAsync(Context);
await base.OnConnected();
}
But then I'm not returning anything. What's the right way to do this?
But then I'm not returning anything. What's the right way to do this?
You don't need to return anything. async Task is the asynchronous equivalent of (synchronous) void. Task means there's no return value, so your code is already correct.
Put another way: async will construct the returned Task/Task<T> for you. So if your method does not have async (as in your first example), you need to return a task; but if your method does have async (as in your second example), then you don't.
If you await HandleConnectionAsync(Context); the method won´t return until that part finishes.
If you don´t want to "block" the hub method, just remote the Wait() part:
public override Task OnConnected()
{
HandleConnectionAsync(Context);
base.OnConnected();
}
That way the method will return immediately before HandleConnectionAsync finishes.

How to await async method inside ExecutePostProcessingAsync

I use the code from http://arcware.net/upload-and-download-files-with-web-api-and-azure-blob-storage/ to upload blobs to azure. With the method ExecutePostProcessingAsync() I would like to call a method that resizes images and that uses async code.
The method i want to use it in looks(shrinked) like this:
public override Task ExecutePostProcessingAsync()
{
//some code
//I would like to await the image resizer method here before going any further
resizer.ScaleImage();
//Some more code here before returning
return base.ExecutePostProcessingAsync();
}
If i add async to the method like this: public override async Task ExecutePostProcessingAsync()
5+ errors will pop up with reference issues and also the error:
"is an async method that returns 'Task', a return keyword must not be followed by an object expression. Did you intend to return 'Task'?"
Questions:
Is there anyway to await an method inside this method? Any help or input appreciated, thanks!
The async keyword enables the use of the await keyword. With that said, the correct syntax is to not return the Task that represents the operation, but rather simply await it. Consider the following:
public override async Task ExecutePostProcessingAsync()
{
await resizer.ScaleImageAsync();
await base.ExecutePostProcessingAsync();
}
Notice how instead of trying to return the Task that represents the base execution, i.e.; base.ExecutePostProcessingAsync() we simply await instead.

Async code misleading in aspnet identity

I need to implement a custom Storage provider for aspnetidentity.
I had a good look round and i found quite a few.However they seem all wrong to me.
My understing is that if you have a method that ends with "async" than it should by asynchronous.
See example taken from somebody's code and this is scattered all over the place.
I find below very misleading since it's not Async at all from what I can see:
public Task<TUser> FindByIdAsync(int userId)
{
TUser result = userTable.GetUserById(userId) as TUser; //this is not async
if (result != null)
{
return Task.FromResult<TUser>(result);
}
return Task.FromResult<TUser>(null);
}
should this be coded like this?:
public async Task<TUser> FindByIdAsync(int userId)
{
TUser result = userTable.GetUserByIdAsync(userId) as TUser;
if (result != null)
{
return await Task.FromResult<TUser>(result);
}
return await Task.FromResult<TUser>(null);
}
Questions?
Is it correct to do "Task.FromResult"? What I mean is does "Task.FromResult actually turns into synchronous? what should it be?
What is the correct way to code the above? what about configureAwait(false)
should async be "All the way down including datalayer to avoid deadlocking"
any sample code /snippet would be appreciated
many thanks for any feedback
The code is not misleading. ASP.NET Identity framework has been designed to provide an asynchronous interface by returning a Task and indicating this by adding the Async suffix to the method name:
Task<TUser> FindByIdAsync(int userId)
However, the underlying provider may not have asynchronous methods. In that case you cannot create an asynchronous implementation but you still have to implement the interface and to do that will have use Task.FromResult exactly as it is done in your first code snippet.
Implementing an asynchronous method using synchronous code
public Task<TUser> FindByIdAsync(int userId)
{
TUser result = userTable.GetUserById(userId) as TUser;
return Task.FromResult<TUser>(result);
}
If your underlying provider supports asynchronous methods you should use async and await.
Implementing an asynchronous method using asynchronous code
public async Task<TUser> FindByIdAsync(int userId)
{
TUser result = (await userTable.GetUserByIdAsync(userId)) as TUser;
return result;
}
Note that Task.FromResult is not used. Task.FromResult is only needed when you have a TResult created by synchronous code and you have to convert it to Task<TResult> required by asynchronous code.
Sometimes your underlying provider can return the desired Task<TUser> without any further work. In that case you can remove the async and await and still provide an asynchronous implementation. This can result in slightly more efficient code:
public Task<TUser> FindByIdAsync(int userId)
{
Task<TUser> result = userTable.GetUserByIdAsync(userId);
return result;
}
The initial code is definitely not asynchronous. It looks like it was put that way to cope with an API design.
However the proposed change doesn't look async to me either. Task.FromResult just creates a completed task with a result, doesn't make anything asynchronous or executes any kind of awaitable code so you should not await on it.
In your case, assuming GetUserByIdAsync returns a Task<TUser>, and assuming the whole purpose of this code (as it seems) is to always return a completed task (never faulted or cancelled), this could be rewritten as:
public async Task<TUser> FindByIdAsync(int userId)
{
var tResult = userTable.GetUserByIdAsync(userId);
TUser result = null;
try
{
result = await tResult;
}
except
{
// Bad idea, but here goes to your first snippet
}
return Task.FromResult<TUser>(result);
}
Note: this is a bad idea as #PanagiotisKanavos commented, it's hiding a possibly faulted state and you won't ever know if your null result came the user not being found, or if there was an error condition: I'd avoid it.
If a faulted/cancelled state is valid, this could simply be:
public Task<TUser> FindByIdAsync(int userId)
{
return userTable.GetUserByIdAsync(userId);
}
An async method is a way for the compiler to build something that will return a promise our future. In the case of the .NET Framework and C#, that is a Task.
The await instruction takes any awaitable and Task just happens to be one. It doesn't know or care if the method/operations being invoked is really asynchronous or not.
Task.FromResult<T> returns a completed task and if you use it in an await instruction inside an async method it will be considered to have been completed synchronously and execution will continue.
So, using async and await with just calls to Task.FromResult<T> ends up just being a waste of CPU cycles and memory by the compiler generating code that will waste more CPU cycles and memory at run time.
Because an async method always returns a Task a decision was made to make it implicit to improve readability and give it some kind of sync feeling. The compile will wrap the return value in a Task. That's why you can't return Task.FromResult<TUser>(result) or Task.FromResult<TUser>(null) directly and are awaiting it to get the value.
So, the async equivalent of your synchronous code would be:
public async Task<TUser> FindByIdAsync(int userId)
{
var result = await userTable.GetUserByIdAsync(userId) as TUser;
if (result != null)
{
return result;
}
return null;
}
Or:
public async Task<TUser> FindByIdAsync(int userId)
{
return await userTable.GetUserByIdAsync(userId) as TUser;
}

Get result from async method

I have this method in my service:
public virtual async Task<User> FindByIdAsync(string userId)
{
this.ThrowIfDisposed();
if (userId == null)
{
throw new ArgumentNullException("userId");
}
return await this.repository.FindByIdAsync(userId);
}
and then in a view I have this code:
using (var service = new UserService(new CompanyService(), User.Identity.GetUserId()))
{
var user = service.FindByIdAsync(id);
}
but the user is the Task and not the User. I tried adding await to the service call, but I can't use await unless the current method is async.
How can I access the User class?
The best solution is to make the calling method async and then use await, as Bas Brekelmans pointed out.
When you make a method async, you should change the return type (if it is void, change it to Task; otherwise, change it from T to Task<T>) and add an Async suffix to the method name. If the return type cannot be Task because it's an event handler, then you can use async void instead.
If the calling method is a constructor, you can use one of these techniques from my blog. It the calling method is a property getter, you can use one of these techniques from my blog.
Using this in async methods without special thread-locked object is dangerous
If you cannot use await, use a code like following.
Task<User> task = TaskFindByIdAsync();
task.Wait(); //Blocks thread and waits until task is completed
User resultUser = task.Result;

Categories