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;
}
}
Related
Say I have two scenarios:
1) WebApi Controller
[System.Web.Http.HttpPost]
[System.Web.Http.AllowAnonymous]
[Route("api/registerMobile")]
public async Task<HttpResponseMessage> RegisterMobile(RegisterModel model)
{
var registerResponse = await AuthUtilities.RegisterUserAsync(model, _userService, User);
if (registerResponse.Success) {
var response = await _userService.GetAuthViewModelAsync(model.Username, User);
return Request.CreateResponse(HttpStatusCode.OK, new ApiResponseDto() { Success = true, Data = response });
}
else {
return Request.CreateResponse(HttpStatusCode.OK, registerResponse);
}
}
2) MVC Controller
[Route("public")]
public async Task<ActionResult> Public()
{
if (User.Identity.IsAuthenticated)
{
var model = await _userService.GetAuthViewModelAsync(User.Identity.Name);
return View("~/Views/Home/Index.cshtml", model);
}
else
{
var model = await _userService.GetAuthViewModelAsync(null);
return View("~/Views/Home/Index.cshtml", model);
}
}
I've been reading up on when I should use ConfigureAwait and it seems like I should use ConfigureAwait(false) on ALL of my async calls that are not tied directly to the UI. I don't know what that means though... should I be using .ConfigureAwait(false) on all of the above await calls?
I'm looking for some unambiguous guidelines around when exactly I should be using it.
This question is NOT the same as the Best practice to call ConfigureAwait for all server-side code - I am looking for a straightforward answer on the use-case for this method in the context of WebApi and MVC, not as general C#.
it seems like I should use ConfigureAwait(false) on ALL of my async calls that are not tied directly to the UI.
Not quite. That guideline doesn't make sense here, since there is no UI thread.
The parameter passed to ConfigureAwait is continueOnCapturedContext, which explains more clearly the scenario. You want to use ConfigureAwait(false) whenever the rest of that async method does not depend on the current context.
In ASP.NET 4.x, the "context" is the request context, which includes things like HttpContext.Current and culture. Also - and this is the undocumented part - a lot of the ASP.NET helper methods do depend on the request context.
(Side note: ASP.NET Core no longer has a "context")
should I be using .ConfigureAwait(false) on all of the above await calls?
I haven't heard any firm guidance on this, but I suspect it's OK.
In my own code, I never use ConfigureAwait(false) in my controller action methods, so that they complete already within the request context. It just seems more right to me.
If there's no actual context in a ASP.NET Core application, it should do no harm nor good to add .ConfigureAwait(false) to your awaitable methods into controllers.
However, if there is a chance that eventually in the future, for whatever reason, there's something like a context to be taken into account as in ASP.NET 4, that would be a different story. We could not risk running in a different context, unless we don't give a damn about it (in which case we could use whatever thread is available for processing, thus possibly improving performance).
My choice here is to add ConfigureAwait(false) even if it's not used.
You may use ConfigureAwait on public action MVC Controller, it help to prevent deal lock if your _userService.GetAuthViewModelAsync keeps waiting.
it cloud raise deadlock if async service keeps await so by may block httpcontext of UI.
Have look below link to understand this case:
http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html
Using ConfigureAwait(false) in controllers does not sound good to me as it will make main thread wait until the operation is finished. The best I figured out is to use it in your Service/Business layer and Persistance layer.
I have very basic fundamental doubt regarding asynchronous Web API programming. I want to make call to SaveCaseSearch in my controller asynchronously. But the call passes through various layers of DAL and eventually calls DB.
Should those consecutive calls also be made asynchronous ?
I am very new to the world of async so I might already have made some mistakes. Just correct me if anything seems wrong.
So for the controller , I am doing something like the below :
/*Create API for Case*/
[HttpPost]
[Route("createcase")]
public IHttpActionResult PostCreateCase([FromBody] ARC.Donor.Business.Case.CreateCaseInput CreateCaseInput)
{
ARC.Donor.Service.Case.CaseServices cs = new ARC.Donor.Service.Case.CaseServices();
var searchResults = cs.createCase(CreateCaseInput);
List<CreateCaseOutput> searchOutputResults = (List<CreateCaseOutput>)searchResults;
if (!string.IsNullOrEmpty(searchOutputResults.ElementAt(0).o_case_seq.ToString()))
SaveCaseSearchDetails(SaveSearchInput); /*This should be called asynchronously*/
return Ok(searchResults);
}
This
SaveCaseSearchDetails
now needs to be called in async mode . So I have written :
[HttpPost]
public async Task<IHttpActionResult> SaveCaseSearchDetails([FromBody] ARC.Donor.Business.SaveSearchInput SaveSearchInput)
{
ARC.Donor.Service.Case.CaseServices cs = new ARC.Donor.Service.Case.CaseServices();
var searchResults = await cs.saveCaseSearchDetails(SaveSearchInput);
}
Then if that is correct
should the consecutive calls be async too ?
For now they are
public IList<Entities.Case.SaveCaseSearchOutput> saveCaseSearch(ARC.Donor.Data.Entities.Case.SaveCaseSearchInput SaveCaseSearchInput)
{
Repository rep = new Repository();
string strSPQuery = string.Empty;
List<object> listParam = new List<object>();
SQL.CaseSQL.getCreateCaseParameters(SaveCaseSearchInput, out strSPQuery, out listParam);
var AcctLst = rep.ExecuteStoredProcedure<Entities.Case.SaveCaseSearchOutput>(strSPQuery, listParam).ToList();
return AcctLst;
}
Is
SQL.CaseSQL.getCreateCaseParameters
method needs to be called in async manner ?
But in that case the immediate next line
rep.ExecuteStoredProcedure
can't execute successfully right ? Because strSPQuery comes from the previous line itself ?
I am thinking in a wrong way ? Please correct me .
Should those consecutive calls also be made asynchronous?
Yes.
SaveCaseSearchDetails now needs to be called in async mode
That's the hard way of doing it.
A much more natural approach is to start at the other end. Whatever part of your code is actually executing the database query should be made asynchronous first. Then you call it using await, which makes those methods async, so they should be called with await, etc., until you finally reach your controller action which is the last thing to be made asynchronous.
actually the problem I am facing is SaveCaseSearchDetails(SaveSearchInput) in PostCaseCreate method needs to be called somewhat async because we don't want to wait for return Ok(searchResults)
Ah, that's a totally different question. You want to return early. Async will not help you do this; as I explain on my blog (and in an MSDN article on async ASP.NET), async does not change the HTTP protocol.
There are a few approaches to returning early or "fire and forget" on ASP.NET that I describe on my blog. However, ASP.NET was not designed for this scenario, so you need to tread carefully. The only fully reliable solution is a properly distributed architecture.
You cannot call SQL.CaseSQL.getCreateCaseParameters in an async manner (with await) since it uses the out keyword which isn't available for async metods.
If you want your DB call to happen async you'll have to find a DB method that you can await. Then you can change the saveCaseSearch method to also be async and await it from your controller method.
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 have MVC 4.0 application targated at targetFramework="4.5".
I have to basically convert the existing functionality of file processing from synchronous to asynchronous (so that for large file user don't have to wait for other task).
My code is
[HttpPost]
public async Task<ActionResult> FileUpload(HttpPostedFileBase fileUpload)
{
Coreservice objVDS = new Coreservice ();
//validate the contents of the file
model =objVDS. ValidateFileContents(fileUpload);
// if file is valid start processing asynchronously
await Task.Factory.StartNew(() => { objVDS.ProcessValidFile(model); }, CancellationToken.None,
TaskCreationOptions.DenyChildAttach,
TaskScheduler.FromCurrentSynchronizationContext());
return view();
}
Basically I want to call a asynchronous method which is in services which does database operations( diffrent project).
I want asynchronous process to have access to the context in services methods. Thats why I am using
TaskScheduler.FromCurrentSynchronizationContext() in Task.Factory.StartNew().
The service method is like following in which, based on file type, a second service is getting called for data operations
public async task ProcessValidFile(fileProcessDataModel model)
{
employeeWorkedDataservice service =new employeeWorkedDataservice()
await Task.Factory.StartNew(() =>
{
service .ProcessEmployeeDataFile(model.DataSetToProcess, OriginalFileName, this, model.Source);
},
CancellationToken.None,
TaskCreationOptions.DenyChildAttach,
TaskScheduler.FromCurrentSynchronizationContext());
}
ProcessEmployeeDataFile returns void and its not asynchronous method.
When the code above is executed it does not return to controller untill it completes the data processing. I think that I am missing something here.
Please guide me to solution.
Thanks,
Amol
Looks like you've misunderstood how await works.
Read this https://msdn.microsoft.com/en-us/library/hh191443.aspx#BKMK_WhatHappensUnderstandinganAsyncMethod
Setting something running in a task will allow it to run asynchronously so you can do something else while it's running.
When you need the result to continue, you use the await keyword.
By creating your task an immediately awaiting it, you're instantly blocking until the task resolves; making it effectively synchronous.
If you're happy to return to your view without waiting for processing to complete, I don't think you need await at all, since at no point do you want to wait for the result of the operation.
public task ProcessValidFile(fileProcessDataModel model)
{
employeeWorkedDataservice service =new employeeWorkedDataservice()
return Task.Factory.StartNew(() =>
{
service.ProcessEmployeeDataFile(model.DataSetToProcess, OriginalFileName, this, model.Source);
},
CancellationToken.None,
TaskCreationOptions.DenyChildAttach,
TaskScheduler.FromCurrentSynchronizationContext());
}
[HttpPost]
public ActionResult FileUpload(HttpPostedFileBase fileUpload)
{
Coreservice objVDS = new Coreservice ();
//validate the contents of the file
model =objVDS. ValidateFileContents(fileUpload);
// if file is valid start processing asynchronously
// This returns a task, but if we're not interested in waiting
// for its results, we can ignore it.
objVDS.ProcessValidFile(model);
return view();
}
Regarding your comments:
I would seriously consider not passing your controller to your service, or having your service rely on the session and context since you're tightly coupling your business logic to your API controller.
Get the bits you need from the controller while you're in it and pass them to your service.
I have to basically convert the existing functionality of file processing from synchronous to asynchronous (so that for large file user don't have to wait for other task).
That's not what async does; as I describe on my blog, async does not change the HTTP protocol.
What you want is some form of "fire and forget" on ASP.NET. I have another blog post that covers a few solutions. Note that using Task.Factory.StartNew is the most dangerous of all these solutions.
The best (read: most reliable) solution is to use a proper distributed architecture: your ASP.NET app should create a description of the work to be done and place that in a reliable queue (e.g., MSMQ); then have an independent backend (e.g., Win32 service) that processes the queue. This is complex, but much less error-prone than attempting to force ASP.NET to do something it was never meant to do.
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