Are there any issues that I might encounter by wrapping a method that returns a
Task<T> where T : ClassA
with a method that returns a
Task<T> where T : IClassA
In other words wrapping a method that returns a Task of some type with another method that returns a Task of the interface of that type as below:
public new Task<ITspIdentity> FindByIdAsync(string id)
{
return new Task<ITspIdentity>(() => base.FindByIdAsync(id).Result);
}
where base.FindByIdAsync(id) would return
Task<TspIdentity>.
Im having a go at decoupling an ASP.NET MVC applications Presentation tier from a dependency on ASP.Identity by using interfaces.
As long as the calling code doesn't depend on a member that is avaliable only via ClassA and not avaliable via IClassA, there shouldn't be a problem.
You are creating and returning a Cold Task which will run an async method synchronously which is a waste of resources. You can refactor that code and simply do:
public new async Task<ITspIdentity> FindByIdAsync(string id)
{
var tspIdentity = await base.FindByIdAsync(id).ConfigureAwait(false);
return (ITspIdentity) tspIdentity;
}
Related
I have a service which is used to get some information and the method has a bunch of async calls in the chain.
public interface IFooService
{
Task<IFoo> GetFooAsync();
}
The concrete class,
public class FooService : IFooService
{
public async Task<IFoo> GetFooAsync()
{
// whole bunch of awaits on async calls and return IFoo at last
}
}
I register this service on StartUp,
services.AddTransient<IFooService, FooService>();
Several other services are injected with this service. One among them,
public class BarService : IBarService
{
private readonly IFooService _fooService;
public BarService(IFooService fooService)
{
_fooService = fooService;
}
public async Task<IBar> GetBarAsync()
{
var foo = await _fooService.GetFooAsync();
// additional calls & processing
var bar = SomeOtherMethod(foo);
return bar;
}
}
IFoo is integral to the application and used across several services. Most of my code is async just due to this one IFooService and the one method it has which returns IFoo.
Considering this use case, I would like to be able to just inject IFoo to all other services as opposed to injecting them with IFooService.
I gave this a shot,
services.AddTransient<IFoo>(provider =>
{
var fooService = provider.GetService<IFooService>();
var foo = fooService.GetFooAsync().GetAwaiter().GetResult();
return foo;
});
but it raises a red flag to me as I'm doing sync over async and I'm unsure if this will cause any issues like race conditions. Would startup be blocked by doing this. Im looking for a clean way to handle this, any recommendation for when we need something like this? Thank you for your help.
I guess what you want is an async constructor, which is not recommended.
here is more info about it and contains a solution using Lazy<T>.
but it raises a red flag to me as I'm doing sync over async
For this red flag, it is caused by that you call method GetFoo which is not defined in IFooService, it is not related with async or sync method.
Try the method which is defined
services.AddTransient<IFoo>(provider =>
{
var fooService = provider.GetService<IFooService>();
var foo = fooService.GetFooAsync().Result;
return foo;
});
2 Other options
Inject Func<Task> as the transient, the caller can await !
Task.Run( async () await abc).Wait(); // this deadlocks much less
due to creating a task and having less issues .
Let's say I have an interface:
interface ILoader()
{
Task<Data> LoadAsync(int id);
}
I have two implementations of this interface:
class NiceDataBase : ILoader
{
public async Task<Data> LoadAsync(int id)
{
//this database has async way of fetching the data
return await NiceDataBaseDriver.LoadDataAsync(id);
}
}
class NotNiceDataBase : ILoader
{
public async Task<Data> LoadAsync(int id)
{
//this database's driver does not have aysnc methods, because it's old or done poorly.
return await Task.Run(() => NotNiceDataBaseDriver.LoadData(id));
}
}
The NotNiceDataBase doesn't provide real async way to load the data, that's why I actually run it on a new thread, which, as I understand, is not really async, because real async does not use a new thread. Is my implementation of NotNiceDataBase a good one then? It kind of cheats the user to think that he is running a real async operation.
What is the optimal way to deal with such situation? I think that the client of NotNiceDataBase should be completely aware what he is doing, otherwise he can't control performance of hiw application well.
My interface could have additional Load method. But in such case, what's the real benefit here? Still LoadAsync of NotNiceDataBase would need to have some implementation. Throwing NotImplementedException is never a good solution I think.
As you know async is an implementation detail and you can not define async on interfaces. So all you have to do is
public class NotNiceDataBase : ILoader
{
public Task<Data> LoadAsync(int id)
{
//this database's driver does not have aysnc methods, because it's old or done poorly.
var result = NotNiceDataBaseDriver.LoadData(id);
return Task.FromResult(result);
}
}
Simply run the method synchronously and return a completed task
e.g.
class NotNiceDataBase : ILoader
{
public Task<Data> LoadAsync(int id)
{
var data = NotNiceDataBaseDriver.LoadData(id);
return Task.From(data);
}
}
You say
I think that the client of NotNiceDataBase should be completely aware
what he is doing, otherwise he can't control performance of hi(s)
application well.
I disagree, if performance is an issue and if they've identified that it's the call to NotNiceDataBase then they can do something about it.
elaboration
Time worrying about how the client is using the interface is almost certainly1 time wasted, and isn't even "premature optimization" but is existential angst over someone else's unknown optimization needs.
1Unless you are your own client, then it's still probably time wasted.
I've a flow: WebApi > ServiceFramework > DBLayer > MongoDB.
Since its a new application, I ensured to have async from the ground up in all layers. However, when my DB Layer has async code, webapi never gets a response back.
API CONTROLLER
[HttpGet]
public IHttpActionResult GetAllRecords()
{
var result = FrameworkApi.GetRecords().Result;
return Ok(result);
}
above calls > FRAMEWORK API
public async Task<List<Record>> GetRecords()
{
return await FrameworkDbApi.GetRecords();
}
above calls > DB FRAMEWORK API (which Calls MongoDB)
public async Task<List<Record>> GetRecords()
{
return await Task.Run(() =>
NoSqlDocumentClient.GetDefaultDatabase().Result.
GetCollection<Record>("record").AsQueryable().ToList());
//following Synchronous version works..but defeats the purpose
//return NoSqlDocumentClient.GetDefaultDatabase().Result
// .GetCollection<Record>("record").AsQueryable().ToList();
}
However, when the operations in either DBLayer or Framework are invoked via test case, I do get result. But when invoked via WebApi controller, the asynchronous version never returns a response while synchronous version works fine.
But when invoked via WebApi controller, the asynchronous version never
returns a response while synchronous version works fine.
That's because your actual request is deadlocking. When you invoke the method via WebAPI, which has a SynchronizationContext, you're seeing the deadlock, in contrary to your test which hasn't got one, when the test runs fine. This is the reason why you shouldn't block on async code.
Your call-chain should look like this in order to avoid deadlocking (this is what it means to go "async all the way":
[HttpGet]
public async Task<IHttpActionResult> GetAllRecordsAsync()
{
var result = await FrameworkApi.GetRecordsAsync();
return Ok(result);
}
public Task<List<Record>> GetRecordsAsync()
{
return FrameworkDbApi.GetRecordsAsync();
}
public async Task<List<Record>> GetRecordsAsync()
{
var result = await NoSqlDocumentClient.GetDefaultDatabase();
return result.GetCollection<Record>("record").AsQueryable().ToList();
}
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;
}
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;