I'm designing a repository, but I have this doubt.
Should I design it to be blocking operations or async?
I tend to think that blocking is more elegant, since users can wrap calls to be async when needed with something like
Task.Run( () => repository.Get(...));
What do you think?
Since underlying data source is naturally asynchronous in most cases (web service, database, file), async API is a preferred way.
blocking is more elegant, since users can wrap calls to be async when needed
Actually, vice versa.
User (not you!) can wrap async call into synchronous one, if needed:
Task<MyObj> DoSomethingAsync() { ... }
MyObj DoSomething()
{
return DoSomethingAsync().Result;
}
while this:
Task.Run( () => repository.Get(...));
is called "async over sync" and must be avoided:
should we expose an asynchronous entry point for a method that’s
actually synchronous? The stance we’ve taken in .NET 4.5 with the
Task-based Async Pattern is a staunch “no.”
Related
I hope this is still on-topic. In this post here I saw how to create an await ViewAsync():
Returning a view with async keyword
So my consideration was: okay, I want to make my application use multithreading, let's make a BaseController that contains those methods for ViewAsync:
just a part of it:
public class BaseController : Controller
{
[NonAction]
public virtual async Task<ViewResult> ViewAsync()
{
return await Task.Run(() => this.View(null));
}
[NonAction]
public virtual async Task<ViewResult> ViewAsync(string viewName)
{
return await Task.Run(() => this.View(viewName, this.ViewData.Model));
}
// the other implementations....
}
now I could always call like this in the inheriting class:
[HttpGet]
public async Task<IActionResult> DoSomething()
{
// maybe we need to do something here, maybe not
return await ViewAsync(new DoSomethingObject());
}
imho, my advantage/target is performance since I always can use multithreading now.
Am I right with my consideration?
In the post, a comment to an answer started with I wouldn't do this. But there aren't many votes/comments/answers.. Where are risks or disadvantages of such an implementation? And maybe, why doesn't Microsoft.AspNetCore.Mvc.Controller come with the method ViewAsync?
Any web app already uses multithreading. When a request comes in, a thread from the thread pool handles it. Your app already handles multiple requests at the same time, without you using Task.Run.
Async/await stuff is useful so that you don't block threads from the thread pool while you wait for async operations to complete (like querying a DB).
Starting new tasks Task.Run on the default thread pool is pretty much useless, unless you are doing some CPU intensive work. Let's say you have an endpoint that calculates the prime numbers up to n on each request, in that case you could delegate a new task on the default thread pool that returns the prime numbers, and have a view that renders them to some html.
Rendering a view has nothing asynchronous about it, so a ViewAsync is not needed. Preparing the data for a view probably is async, but the rendering is not. Also, having a ViewAsync would probably over complicate the template syntax.
I m trying to write an async service with ServiceStack and to me it seems that this feature is not really complete.
My questions:
1) How do you pass CancellationTokens in the service methods?
2) What about ConfigureAwait(false) in those methods? For example
public Task<SomeResponse> Get(SomeRequest request)
{
return _manager.ExecuteAsync(request).ConfigureAwait(false);
}
This doesnt compile.
3) Should we be marking such services with the async keyword and return Task to make them awaitable? For example this doesnt work (usage is silly but you get the point)
public async Task<SomeResponse> Get(SomeRequest request)
{
return await _manager.ExecuteAsync(request).ConfigureAwait(false);
}
Should we even be writing async services with ServiceStack? Is there a benefit or the current implementation defeats the purpose?
Thanks
If the methods don't accept cancellation tokens, then they weren't designed to be cancellable, and you can't cancel them.
You're not actually awaiting the task, so there's no await to configure. Just omit the ConfigureAwait since you have no await to configure.
There's no need to mark a method as async if you're not actually going to leverage any of the features of it or accomplish anything with it that isn't already done by just not doing that. It's not breaking anything other than making the code a tiny bit slower, but it's not adding anything either.
You can make an async request as normal using C# async/await, i.e:
var response = await client.GetAsync(requestDto);
Or if you prefer (or cannot use await), you can use Continuations on the returned Task<T>, e.g:
client.GetAsync(new Hello { Name = "World!" })
.Success(r => r => r.Result.Print())
.Error(ex => { throw ex; });
You can cancel an async request with:
client.CancelAsync();
This calls HttpWebRequest.Abort() behind the scenes.
I've just, for a rough draft, converted a whole lot of data access methods to async using the following pattern, and it looks too simple to be good enough for later iterations. How safe is it, what is missing, and how should I be doing it?
The service that provides long-running calls:
private class UserService
{
public IdentityUser GetById(int id)
{
...
}
}
private UserService _userService = new UserService();
The original synchronous method:
public IdentityUser GetById(int id)
{
return _userService.GetById(id);
}
My fantastic new async method:
public async Task<IdentityUser> GetByIdAsync(int id)
{
await Task.Run(() => _userService.GetById(id));
}
You should not make "fake async" methods like this:
public async Task<IdentityUser> GetByIdAsync(int id)
{
await Task.Run(() => _userService.GetById(id));
}
The reason I call it "fake async" is because there is nothing intrinsically async about the operation. In this case, you should have only the synchronous method. If a caller wants to make it async by using Task.Run, he can do that.
When is something intrinsically async? When you make a request to a web service or a database, for example, between sending the request and receiving the response there is a waiting period - the request is an intrinsically async operation. To avoid blocking the calling thread, use async-await.
Technically, that works, but it works by creating a new thread to perform a synchronous operation, which itself is wrapping and blocking on an inherently asynchronous operation. That means you're not getting some of the biggest benefits of going async in the first place.
The right way is to go asynchronous all the way. Whereas right now you probably have something like this:
private class UserService
{
public IdentityUser GetById(int id)
{
return mContext.Users.Single(u => u.Id == id);
}
}
... you should now create an async version:
private class UserService
{
public async Task<IdentityUser> GetByIdAsync(int id)
{
return await mContext.Users.SingleAsync(u => u.Id == id);
}
}
Usage:
public async Task<IdentityUser> GetByIdAsync(int id)
{
return await _userService.GetByIdAsync(id);
}
Supposing, of course, that your underlying framework supports asynchronous methods like SingleAsync() for inherently asynchronous operations, this will allow the system to release the current thread while you wait for the database operation to complete. The thread can be reused elsewhere, and when the operation is done, you can use whatever thread happens to be available at that time.
It's probably also worth reading about and adopting these Best Practices. You'll probably want to use .ConfigureAwait(false) anywhere that you're not accessing contextual information like sessions and requests, for example.
This answer assumes, of course, that GetById is inherently asynchronous: you're retrieving it from a hard drive or network location or something. If it's calculating the user's ID using a long-running CPU operation, then Task.Run() is a good way to go, and you'll probably want to additionally specify that it's a long-running task in the arguments to Task.Run().
Task.Run () should only be used for CPU-bound work. Don't quite remember why though.
Try to make a GetByIdAsync () method instead, that ultimately calls an async resource.
I am writing a WCF webservice that includes a method that accepts an array of objects and inserts them into the database. This could take a long time, so I can't just expect the client to wait.
My colleague thinks that I don't need to do anything, that it's the client's job to call my service asynchronously. I just write a normal method. This doesn't sound right to me, although I hope it's true because looking at WCF async tutorials and SO questions has just confused me so far.
Is he correct? If not, how do I actually write the method in a way that would allow the client to call the method asynchronously or otherwise avoid hanging?
If he is correct (as appears to be the case), then what is the point of defining an asynchronous method ([OperationContract (AsyncPattern=true)], Begin, End, etc.). Is it a way explicitly handling asynchronous calls, or allowing interactivity, or what?
It should fall on the client's side. They are the ones that have to prevent their app/UI from hanging.
Have your client call your method asynchronously. If they are using a service reference, all methods/events are generated automatically.
myWcfClient.myMethodCompleted
+= new EventHandler<myMethodCompletedEventArgs>(myCallBack);
myWcfClient.myMethodAsync(args);
public void myCallback(object sender, myMethodCompletedEventArgs e)
{
var myResult = e.Result;
}
If your client doesn't care what happens with the service call, you want a simple fire and forget operation and you can do this.
The AsyncPattern property tells the runtime that your operations implement the .NET Framework asynchronous method design pattern. See here. If you want your client application to know what has happened with your service call then you can use this pattern. There are other ways to get the results though.
This is only on the client side, I've skipped the old event driven async bleh pattern and replaced it with the async-await pattern. Not waiting for webmethod calls async, and blocking the UI... doesn't even belong in this century ;)
If you are using .net 4.5+ you are getting the async-await pattern for free (Unless wp8, where you still have to wrap it). The async methods should already be avaliable through the service. I recommend the AsyncBridge if you are using old frameworks, which allows you to use the async-await pattern for cases like this. The alternative is to stick to the old event driven async nightmare. The examples below is only possible if you are using C#5.0 or never.
Ensure to start in a new thread from a non async method.
Task.Factory.StartNew(client.DoSomethingAsync("blabla") ).ContinueWith(...);
The last part is run after your method has completed, check for exceptions to completion code etc.
Or in some async method
public async Task<string> DoSomethingAsync(String text) {
// Exception handling etc
return await client.DoSomethingAsync(text);
}
wrapping APM to async-await pattern:
public class ServiceWrapper : IServiceWrapper
{
readonly YourServiceClient client;
public ServiceWrapper(YourServiceClient client)
{
this.client = client;
}
public async Task<string> DoSomethingAsync(string someParameter)
{
return await Task<string>.Factory.FromAsync(client.BeginDoSomeStuff, client.EndDoSomeStuff, someParameter, new object());
}
}
EDIT
Opening and closing connections in a wrapped service. (I don't have my devbox avaliable right now but this should work).
public class ServiceWrapper : IServiceWrapper
{
EndpointAddress address;
public ServiceWrapper(EndpointAddress clientAddress)
{
address = clientAddress;
}
public async Task<string> DoSomethingAsync(string someParameter)
{
// handle exceptions etc here, can be done some cleaner..
var client = new YourServiceClient();
client.Endpoint.Address = address.Address; // can skip this..
await client.OpenAsync()
var res = await Task<string>.Factory.FromAsync(client.BeginDoSomeStuff, client.EndDoSomeStuff, someParameter, new object());
await client.CloseAsync();
return res;
}
}
One last thing I'm not sure how you generate your proxy, if you are using vs make sure to hook of the checkbox allowing async methods when configuring the service. If you are using svcutil add the appropriate flags.
Async-await pattern
Old event driven async pattern
Hope it helps,
Cheers,
Stian
My MVC application consumes a library and some methods of this library call WCF service internally. All methods exposed from this DLL are sync (none of them return Task or Task) and since we don't own that assembly, it is not possible to convert them into Async API.
However, because these methods call WCF service, they are network bound (so ideally they should be async).
I want to use async controller actions in my MVC application to make it more scalable. My question is how to make the entire method pipeline await able when one method is sync in nature.
Async action --> await async method --> await async method 2 --> sync method from library?
Should I use TaskCompletionSource or Task.FromResult to wrap the library method call?
Also, if I use above approach, will my code more scalable than sync version?
My question is how to make the entire method pipeline await able when one method is sync in nature.
You can't. The only solution is to rewrite the dll.
Should I use TaskCompletionSource or Task.FromResult to wrap the library method call?
Neither.
Also, if I use above approach, will my code more scalable than sync version?
No. It will be slightly less scalable.
TaskCompletionSource<T> is a way to create a puppet Task, which can complete at any point you like, and can make it fault at any point you like. This means, this would ideal in your case since you have no control over the API method, which you are trying to consume. Following example will give you a head start.
public class HomeController : Controller
{
public async Task<ActionResult> Index()
{
ViewBag.Message = await ProcessRequest();
return View();
}
//TResult -> can be of any built-in or custom type that you should decide.
Task<TResult> ProcessRequest()
{
// Make a TaskCompletionSource so we can return a puppet Task
TaskCompletionSource<TResult> tcs = new TaskCompletionSource<TResult>();
// Call your sync API method
SyncAPI syncApi = new SyncAPI();
// Call api method and set the result or exception based on the output from the API //method.
tcs.SetResult(TResult);
// Return the puppet Task, which isn't completed yet
return tcs.Task;
}
}