I'm using Visual Studio 2012 RC with .Net 4.5 and ASP MVC 4 RC. It hangs whenever I use async at all. The controller action method uses async but is not itself an async controller method.
There are no errors logged or exceptions thrown, but the browser shows "Waiting for www.myweb.local" forever.
// Simplest possible async
public class Waiter
{
public async Task<int> GetValue()
{
await Task.Yield();
return await Task.Factory.StartNew(() => 42);
}
}
// simplest possible controller that uses the async
public class HomeController : Controller
public ActionResult Index()
{
var waiter = new Waiter();
var resultTask = waiter.GetValue();
int result = resultTask.Result;
// it never gets here
return View();
}
}
I have done the things that are noted in this answer, and it still does not work.
ie. The web.config contains
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true"/>
And the magic words await Task.Yield(); are in the async method.
The .Net framework version is 4.5.50501. I have observed this behaviour on IIS Express and on IIS 6.0.
I tried applying the "July 2012 update" to VS2012, but that did not fix it.
This answer suggests that it may be because the task is already completed when I wait for it, however if that was the case, this should work and it does not:
public class Waiter
{
public async Task<int> GetValue()
{
await Task.Yield();
return await Task.Factory.StartNew(() =>
{
Thread.Sleep(1500);
return 42;
});
}
}
A couple of people have suggested that ConfigureAwait(false) is needed, but this code does not work either:
public async Task<int> GetValue()
{
var task = new Task<int>(() => 42);
return await task.ConfigureAwait(false);
}
The following does work with the razor view engine, but not with spark. Surely there should be a way to get the other scenario working as well? Can one not use the async Tasks inside synchronous code?
public class Waiter
{
public async Task<int> GetValue()
{
return await Task.Factory.StartNew(() => 42);
}
}
public class HomeController : Controller
{
public async Task<ActionResult> IndexAsync()
{
await Task.Yield();
var waiter = new Waiter();
int result = await waiter.GetValue();
return View();
}
}
I know that is this isn't released software, but Microsoft's RCs are usually quite stable, so I'm surprised that it fails, and fails in an unhelpful way.
You are causing a deadlock, just like this question.
James Manning's suggestion is correct, but you have to await the result of ConfigureAwait, like this:
public async Task<int> GetValue()
{
var task = new Task<int> (() => 42);
return await task.ConfigureAwait(false);
}
In general, mixing synchronous and asynchronous code is a Really Bad Idea unless you Really Know what you're doing. Making the controller action asynchronous would be much better.
I have had async working in the beta just fine. I've not tested it, but I'm guessing it's because your controller method is not async. Change it to this:
public async Task<ActionResult> IndexAsync()
{
var waiter = new Waiter();
int result = await waiter.GetValue();
// it never gets here
return View();
}
Related
I am working on an ASP.NET Core 2.2 application with Dapper. Virtually all methods follows the async/await pattern returning some sort of Task as a result.
Due to an issue we had with Dapper (I haven't personally investigated it, this part of the code I use as it is) but basically it boils down to the fact that if you want to execute in Transaction multiple async methods, which internally are calling other async methods and you may have several levels of nesting this way, you need to wrap all those method invocations within a single method which would be executed in a transaction.
The method that handles this is as follows:
public async Task<TOut> ExecuteInTransactionAsync<TOut>(
Delegate function,
params object[] parameters)
{
using (var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
{
var result = await ((Task<TOut>)function.DynamicInvoke(parameters))
.ConfigureAwait(false);
scope.Complete();
return result;
}
}
So I have a very complex Entity which is saved by calling Save to a lot of smaller entities. This part of the code is working OK and looks like this:
public async SaveEntireEntity(EntityDTO entityDTO)
{
return await _transactionProvider.ExecuteInTransactionAsync<dynamic>(
new Func<object, Task<dynamic>>(async dto => await SaveInTransaction(dto)),
new { Name = entityDTO.Name, Address = entityDTO.Address, Age = entityDTO.Age });
}
And the SaveInTransaction method looks like:
private async Task<dynamic> SaveInTransaction(dynamic dto)
{
var entityId = await nameService.Add(dto.Name);
await addressService.Add(dto.Address);
await ageService.Add(dto.Age);
return entityId;
}
so this is simplified, but indeed I am calling a multiple services here, which on their part are calling multiple repositories and this works fine.
The Problem I have is when it comes to updating the same entity within a transaction. The whole purpose of showing the Save logic was to point out that at the end because I have this return entityId; I am able to chain everything together without any problems. However, as it is right now, by default our Update methods are not returning anything and this is where I can't figure out how to implement the Update logic.
Currently I have this:
public async Task UpdateEntireEntity(UpdateEntityDTO, entityDTO)
{
await _transactionProvider.ExecuteInTransactionAsync<dynamic>(
new Func<object, Task<dynamic>>(async dto => await UpdateInTransaction(dto)),
new { Name = entityDTO.Name, Address = entityDTO.Address, Age = entityDTO.Age });
}
And UpdateInTransaction looks like this:
private async Task<dynamic> UpdateInTransaction(dynamic dto)
{
await UpdateName(dto.Name);
await UpdateAddress(dto.Address);
await UpdateAge(dto.Age);
return await Task.FromResult<dynamic>(null);
}
This seems to work at least based on the several tests I made, however I really don't like this part:
return await Task.FromResult<dynamic>(null);
To me it seems like an ugly hack. The Update methods were thought not to return any value and this is just too artificial.
And even the worst part is that I can not figure out how implement the update method without having to return something.
One thing I've tried is to change the declaration of UpdateInTransaction to
private async Task UpdateInTransaction(dynamic dto)
and when I call the method I change it to:
await _transactionProvider.ExecuteInTransactionAsync<dynamic>(
new Func<object, Task>( async dto => await UpdateInTransaction(dto)..
But I got the following exception:
AsyncStateMachineBox1[System.Threading.Tasks.VoidTaskResult,
<fully-qualified- name>.<<UpdateEntireEntity>b__0>d] to type
'System.Threading.Tasks.Task1[System.Threading.Tasks.Task]'
.
So basically that's it. Sorry for the long post. I would really appreciate some well explained answer.
I would avoid the use of Delegate since it isn't typed:
public async Task<TOut> ExecuteInTransactionAsync<TOut>(Func<Task<TOut>> function)
{
using (var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
{
var result = await (function()).ConfigureAwait(false);
scope.Complete();
return result;
}
}
This signature would mean you'd need to capture parameters rather than pass them:
public async Task<dynamic> SaveEntireEntity(EntityDTO entityDTO)
{
return await _transactionProvider.ExecuteInTransactionAsync(
async () => await SaveInTransaction(
new { Name = entityDTO.Name, Address = entityDTO.Address, Age = entityDTO.Age }));
}
Once you're using the strongly-typed Func<Task<T>> instead of Delegate in your method signature, you can create an overload for ExecuteInTransactionAsync as such:
public async Task ExecuteInTransactionAsync(Func<Task> function)
{
using (var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
{
await (function()).ConfigureAwait(false);
scope.Complete();
}
}
which can be used as such:
public async Task UpdateEntireEntity(UpdateEntityDTO entityDTO)
{
await _transactionProvider.ExecuteInTransactionAsync(
async () => await UpdateInTransaction(
new { Name = entityDTO.Name, Address = entityDTO.Address, Age = entityDTO.Age }));
}
private async Task UpdateInTransaction(dynamic dto)
{
await UpdateName(dto.Name);
await UpdateAddress(dto.Address);
await UpdateAge(dto.Age);
}
You can change
private async Task<dynamic> UpdateInTransaction(dynamic dto)
{
await UpdateName(dto.Name);
await UpdateAddress(dto.Address);
await UpdateAge(dto.Age);
return await Task.FromResult<dynamic>(null);
}
to
private async Task<dynamic> UpdateInTransaction(dynamic dto)
{
await UpdateName(dto.Name);
await UpdateAddress(dto.Address);
await UpdateAge(dto.Age);
return null;
}
I've been banging my head against a wall for two days now, and frankly I'm annoyed with myself because I just can't seem to get it.
I'm in a webapi context. During this request I need to send some data to one of our other systems, this system is slow to return, due to heavy calculations and multiple database saves etc etc. I need to log the result of this operation, regardless of whether it is successful or not. But I don't want to wait around for it to finish.
I've read that I should be async await all the way from top to bottom. I would have to convert numerous methods if I decided to do this, as I'm already 3 or 4 methods deep, which I fear would branch out even more.
What are my options here? If I go async await all the way down, what do I do with the methods higher up the stack, like my WebApi controllers?
Here is my code, I've tried to thin it down as much as I can. Right now I'm using Task.Result() in the method PushResult(). Which to my understanding is blocking the async? This code works in that the request gets sent. But the TestLog is always last, not first. Therefore not async.
//I'm in a public service and referenced twice
private void MyEndProcess()
{
// other stuff
_vendorPushService.PushResult(); // This could take a while and I have to wait for it!
_logService.PostLog(LogType.TestLog, "Test");
}
//I'm referenced above and somewhere else in the code base
public void PushResult()
{
ExternalResultModel externalResultModel = _resultService.GetExternalResultModel();
PushedResultModel pushedResult = new PushedResultModel();
try
{
pushedResult = _vendorRequestService.PushResultAsync(externalResultModel).Result;
}
catch (Exception ex)
{
pushedResult.Success = false;
}
if (pushedResult.Success)
{
_logService.PostLog(LogType.SuccessLog, pushedResult.Message);
}
else
{
_logService.PostLog(LogType.FailedLog, pushedResult.Message);
}
}
public async Task<PushedResultModel> PushResultAsync(ExternalResultModel externalResultModel)
{
// setup the requestMessage
HttpResponseMessage responseMessage = await _httpRequestService
.SendRequest(requestMessage)
.ConfigureAwait(false);
return new PushedResultModel
{
Success = responseMessage.IsSuccessStatusCode,
Message = await responseMessage.Content.ReadAsStringAsync()
};
}
public class HttpRequestService : IHttpRequestService
{
private readonly HttpClient _httpClient;
public HttpRequestService(IHttpClientAccessor httpClientAccessor)
{
_httpClient = httpClientAccessor.HttpClient;
}
public async Task<HttpResponseMessage> SendRequest(HttpRequestMessage requestMessage)
{
HttpResponseMessage httpResponseMessage = await _httpClient.SendAsync(requestMessage).ConfigureAwait(false);
return httpResponseMessage;
}
}
You should implement async await all the way from top to bottom.
If I go async await all the way down, what do I do with the methods higher up the stack, like my WebApi controllers?
Just make your controller actions async like this:
[RoutePrefix("api")]
public class PresidentsController : ApiController
{
[Route("presidents")]
public async Task<IHttpActionResult> GetPresidents()
{
await Task.Delay(TimeSpan.FromSeconds(10)).ConfigureAwait(false);
return Ok();
}
}
It's easiest way to implement async methods. Even if it will add some work to change everything to async it will benefit in future, because You will avoid many problem with async code.
If you absolutly HAVE to use async method in synchronous methods make it block in ONE place, like this:
public void MySyncMethod()
{
try
{
this.MyAsyncMethod().Wait();
}
catch (Exception exception)
{
//omited
}
}
private async Task MyAsyncMethod()
{
await AsyncLogic().ConfigureAwait(false);
}
But i don't recommend it. You should just use async await all the way to controller action.
In your comment you said you want to process a task in the background and not make the client calling your API wait. To do that, you don't really need to use async/await.
Try this:
private void MyEndProcess()
{
// other stuff
Task.Run(_vendorPushService.PushResult()).ConfigureAwait(false); //fire and forget
_logService.PostLog(LogType.TestLog, "Test");
}
The Task.Run will start the task, and the ConfigureAwait(false) tells it that it does not need to resume on the same context that we're currently on (meaning that the context can close before the task is finished - i.e. the response can be sent back without waiting for the task to finish).
You will get a compiler warning that you're not awaiting Task.Run, but that's what you want.
Keep in mind that when you do this, HttpContext.Current will not be available inside PushResult.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
I have a complex method, this method make webRequest, access database and other jobs.
public string MyComplexMethod(params){
//Access db
//Make WebRequests
//...
}
I made this method asynchronous this way:
public async Task<string> MyComplexMethod(params)
{
//Access db
//Make WebRequests
//...
}
public async Task MyComplexMethodAsync(params)
{
await Task.Run(() => MyComplexMethod()).ConfigureAwait(false);
}
And I call my complex method this way:
public void OtherMethod()
{
//other stuff
MyComplexMethodAsync(params);
//other stuff
}
Can I use async and mainly Task.Run with such complex method?
Or there another way to make this method asynchronous?
To be wrapped by Task.Run method don't need to be asynchronous
public string MyComplexMethod() {}
public Task MyComplexMethodAsync()
{
return Task.Run(() => MyComplexMethod());
}
But using sample above don't make your method to be asynchronous in the way async-await works.
You mentioned that your complex method uses webservices and database queries - this makes your method to be perfect candidate for making it asynchronous.
async-await was designed mostly for working with external resources effectively without using extra threads for operations which only waiting for response and do nothing.
Only you need, it creates own asynchronous method for every operation which "touches" external resources, most of the "clients" already provide asynchronous methods for working with databases or web services.
// Access Db
public async Task<object> GetValueFromDatabaseAsync()
{
using (var connection = new SqlConnection(connectionString))
using (var command = new SqlCommand(query, connection))
{
await connection.OpenAsync();
return await command.ExecuteScalarAsync();
}
}
// Make web request
public async Task<HttpResponseMessage> SendRequestToWebServiceAsync(SomeData data)
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(webserviceUrl);
return await client.PostAsJsonAsync("api/values", data);
}
}
Then you end up with your asynchronous complex method
public async Task<string> MyComplexMethodAsync()
{
var value = await GetValueFromDatabaseAsync();
var data = new SomeData(value);
var response = await SendRequestToWebServiceAsync(data);
return response.StatusCode.ToString();
}
Interesting part of asynchronous approach, that after you starting using async-await methods in your application they starts spreading over whole application like a zombies :)
For using MyComplexMethodAsync yuo need change OtherMethod to be asynchronous too
public async Task OtherMethodAsync()
{
//other stuff
await MyComplexMethodAsync(params);
//other stuff
}
I think you're on the right path with async / await.
async tells the compiler that you are going to wrap everything in that method ContinueWith AFTER you reach the await keyword.
public void Something()
{
var task = new Task(() => DoWork());
task.ContinueWith(() => MoreWorkAfter());
task.Start();
}
//Is the same as
public async void Something()
{
var task = new Task(() => DoWork());
task.Start();
await Task;
MoreWorkAfter();
}
//Is also the same as
public async void Something()
{
var task = Task.Run(() => DoWork());
await Task;
MoreWorkAfter();
}
//Still the same as
public async void Something()
{
await Task.Run(() => DoWork());
MoreWorkAfter();
}
To make the method itself awaitable it has to return a Task object also because Task has the GetAwaiter() the await is looking for. Just remember that if you don't START the task it will await forever. So here's the same method written in an awaitable way for others.
public Task SomethingAsync()
{
return Task.Run(() => DoWork());
}
//Same as...
public async Task SomethingAsync()
{
await Task.Run(() => DoWork());
}
//And now in other methods you can....
public async void AnotherMethod()
{
await SomethingAsync();
//Do more work after it's complete.
}
Something to take away is that the Task is running on a new thread once it's started and to answer your question, yes it offloads the work. So for your original method keep it the same. The async method can Task.Run it like you've done.
public string MyComplexMethod(params)
{
//Access db
//Make WebRequests
//...
}
public async Task MyComplexMethodAsync(params)
{
await Task.Run(() => MyComplexMethod()).ConfigureAwait(false);
}
Something to note however; is that although you may call:
await MyComplexMethodAsync(params);
You have ConfigureAwait(false);
Which means any code after the task, in that method, will not be on the current context.
public async Task MyComplexMethodAsync(params)
{
//Main thread work here
await Task.Run(() => MyComplexMethod()).ConfigureAwait(false);//Background work here
//This will also be background work since CongfigureAwait(false);
}
public async Task MyComplexMethodAsync(params)
{
//Main thread work here
await Task.Run(() => MyComplexMethod()); //Background work here
//Main thread work here again since CongfigureAwait defaults to true;
}
And I say Main thread work but that assumes the Main thread called MyComplexMethodAsync.
The easiest way to grasp it is just imagine everything AFTER the await keyword is basically a new Action that gets called when the task is complete; just like using ContinueWith.
AND if there is code AFTER the await keyword in your method, it will BE SCHEDULED to run on the Main thread (considering the Main thread called the method to start with). Meaning it's a little like using Dispatcher.BeginInvoke if you've ever use it. The remaining portion get's queued to run on the Main thread in better terms. (Again, unless you put ConfigureAwait(false) and then it doesn't)
I had set up my controller and service layer to not use async and Task originally. I updated my code (below). Is this the correct way to use async, Task, and await? Will my code benefit long term as number of users grow?
Controller:
public async Task<IHttpActionResult> All()
{
var warmup = await _warmupService.GetAllAsync();
if (warmup != null)
return Ok(warmup);
return NotFound();
}
The Controller calls this method in my service layer:
public async Task<Warmup> GetAllAsync()
{
return await Task.Run(() => GetWarmup());
}
GetWarmup() (also in Service) makes a DB call using EF6:
private Warmup GetWarmup()
{
var warmup = new Warmup();
var factoryTools = _db.FactoryTools.Select(tool => new { tool.Factory });
}
It is not the best way to do it. If you can, avoid using Task.Run when your underlying code provides a Task or Task<T> you can await.
Instead of using Task.Run in this piece of code
public async Task<Warmup> GetAllAsync()
{
return await Task.Run(() => GetWarmup());
}
and using this:
private Warmup GetWarmup()
{
var warmup = new Warmup();
var factoryTools = _db.FactoryTools.Select(tool => new { tool.Factory });
}
you should use the native async methods provided by the Entity Framework like demoed here: https://msdn.microsoft.com/en-us/library/jj819165(v=vs.113).aspx
So your GetWarmUp() should be async Task<Warmup>() and call one of the native async methods of the Entity Framework.
See https://msdn.microsoft.com/en-us/library/system.data.entity.queryableextensions(v=vs.113).aspx for a list of available async extension methods.
Error in line: await instance.CreateFile(); The await operator can only be used within an async method. Consider marking this method with the async modifier and changing its return type to Task
It's my understanding that the method is already asynchronous, I'm not sure what I am doing wrong. This is on a UWP app in VS 2015.
public sealed partial class MainPage : Page
{
private List<Customer> Customers;
public MainPage()
{
this.InitializeComponent();
CustomerDataAccessLayer instance = new CustomerDataAccessLayer();
await instance.CreateFile();
}
}
public class CustomerDataAccessLayer
{
public StorageFile mfile;
public async Task CreateFile()
{
mfile = await ApplicationData.Current.LocalFolder.GetFileAsync("Customers.xml");
if (mfile == null)
{
mfile = await ApplicationData.Current.LocalFolder.CreateFileAsync("Customers.xml", CreationCollisionOption.ReplaceExisting);
}
else
{
}
return;
}
}
As others have noted, the error message is complaining that the calling method is not async, but constructors cannot be marked async.
The core problem is that your UI cannot load asynchronously - it must load immediately. I recommend initially loading some kind of "Loading..." state and also starting an asynchronous operation. Then, when that operation completes, update the UI to display the data.
To start an asynchronous action from a synchronous function (like a constructor), you can use a Task.
Task.Run(async () =>
{
//put your async code here
});
To await this Task, you have to use some more code.
Task t = new Task(() => { /*Your code*/ });
t.Wait();