I want to use recent C# 5.0 async methods, however some specific way.
Consider following example code:
public abstract class SomeBaseProvider : ISomeProvider
{
public abstract Task<string> Process(SomeParameters parameters);
}
public class SomeConcreteProvider1 : SomeBaseProvider
{
// in this method I want to minimize any overhead to create / run Task
// NOTE: I remove here async from method signature, because basically I want to run
// method to run in sync!
public override Task<string> Process(SomeParameters parameters) {
string result = "string which I don't need any async code to get";
return Task.Run(() => result);
}
}
public class SomeConcreteProvider2 : SomeBaseProvider
{
// in this method, it's OK for me to use async / await
public async override Task<string> Process(SomeParameters parameters) {
var data = await new WebClient().DownloadDataTaskAsync(urlToRequest);
string result = // ... here we convert data byte[] to string some way
return result;
}
}
Now how I am going to use async methods (you can ignore fact that consumer actually ASP.NET MVC4 app in my case... it can be anything):
public class SomeAsyncController : AsyncController
{
public async Task<ActionResult> SomethingAsync(string providerId)
{
// we just get here one of providers I define above
var provider = SomeService.GetProvider(providerId);
// we try to execute here Process method in async.
// However we might want to actually do it in sync instead, if
// provider is actually SomeConcreteProvider1 object.
string result = await provider.Process(new SomeParameters(...));
return Content(result);
}
}
As you can see I have 2 implementations, each one will perform differently: one I want to run in async and do not block thread (SomeConcreteProvider2), while another one I want to be able to run in sync and do not create any Task object etc (which I fail to code in code above, i.e. I do create new Task here!).
There are questions already like How would I run an async Task<T> method synchronously?. However I don't want to run something in sync... I want to avoid any overhead if I know at code time (i.e. before runtime) that some methods implementations will NOT actually be async and will not need to use any threads / I/O completion ports etc. If you check code above, its easy to see that method in SomeConcreteProvider1 basically will construct some string (html), can do it very quickly at the same execution thread. However same method in SomeConcreteProvider2 will need to create Web Request, get Web Response and process it someway and I do want to make at least Web Request in Async to avoid blocking of whole thread during request time (may be quit long time actually).
So the question is: how to organize my code (different method signatures or different implementations, or?) to be able to decide how to execute method and avoid ANY possible overhead which caused for example by Task.Run(...) in SomeConcreteProvider1.Process method?
Update 1: obvious solutions (I think up some of them during question process), such as for example to add some static property to each of providers (say 'isAsyncImplementation') and then check that property to decide how to run method (with await or without await in controller action) have some overhead too :D I want something better if possible :D
Solution A If you have a simple asynchronous method that doesn't need to synchronize back to its context, then you can use Task. WaitAndUnwrapException : var task = MyAsyncMethod(); var result = task. WaitAndUnwrapException();
Naming Convention By convention, you append "Async" to the names of methods that have an async modifier. You can ignore the convention where an event, base class, or interface contract suggests a different name. For example, you shouldn't rename common event handlers, such as Button1_Click .
No, it does not. It MAY start another thread internally and return that task, but the general idea is that it does not run on any thread.
The async and await keywords don't cause additional threads to be created. Async methods don't require multithreading because an async method doesn't run on its own thread. The method runs on the current synchronization context and uses time on the thread only when the method is active.
In your first case, I would recommend returning:
Task.FromResult(result)
which returns a ready-completed task.
http://msdn.microsoft.com/en-us/library/hh194922%28v=vs.110%29.aspx
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With