我试图理解为什么ASP.Net应用程序中的异步void方法可能导致以下异常,而async Task似乎不会:
System.InvalidOperationException: An asynchronous module or handler
completed while an asynchronous operation was still pending
Run Code Online (Sandbox Code Playgroud)
我对.NET中的异步世界相对较新,但我觉得我试图通过一些现有资源来运行这个,包括以下所有内容:
从这些资源中,我了解最佳做法是通常返回Task并避免异步void.我也理解async void会在调用方法时增加未完成操作的数量,并在完成时减少它.这听起来至少是我问题答案的一部分.但是,我遗漏的是当我返回Task时会发生什么,以及为什么这样做会让事情变得"有效".
这是一个人为的例子来进一步说明我的问题:
public class HomeController : AsyncController
{
// This method will work fine
public async Task<ActionResult> ThisPageWillLoad()
{
// Do not await the task since it is meant to be fire and forget
var task = this.FireAndForgetTask();
return await Task.FromResult(this.View("Index"));
}
private async Task FireAndForgetTask()
{
var task = Task.Delay(TimeSpan.FromSeconds(3));
await task;
}
// This …Run Code Online (Sandbox Code Playgroud) 在C#中,当覆盖方法时,允许在原始方法不是时使覆盖异步.这似乎很糟糕.
令我惊讶的问题是:我被引入以协助负载测试问题.在大约500个并发用户中,登录过程将分解为重定向循环.IIS正在使用消息"在异步操作仍处于挂起状态时完成异步模块或处理程序"来记录异常.一些搜索让我觉得有人在滥用async void,但我对源头的快速搜索一无所获.
可悲的是,我正在寻找async\s*void(正则表达式搜索)我应该寻找更多的东西async\s*[^T](假设任务不完全合格......你明白了).
我后来发现的是async override void onActionExecuting在一个基本控制器中.显然,这必须是问题,而且确实如此.修复它(使其暂时同步)解决了问题.
但它给我留下了一个问题:为什么当调用代码永远不会等待它时,你可以将覆盖标记为异步?
我的应用程序中有3个任务负责从数据库中获取数据.
直到现在我已经一个接一个地执行了所有任务.如果第一次完成并有结果然后这是我的数据,如果现在我开始第二个任务,我再次检查.
最近我发现了一些信息,我可以启动多个任务,并在其中一个完成使用后继续Task.Factory.ContinueWhenAny.如果我的所有任务都没有抛出任何异常,这可以正常工作,但如果任何任务失败,我无法得到我想要的结果.
例如:
var t1 = Task.Factory.StartNew(() =>
{
Thread.Sleep(5000);
return 1;
});
var t2 = Task.Factory.StartNew(() =>
{
Thread.Sleep(2000);
throw new Exception("My error");
return 2;
});
var t3 = Task.Factory.StartNew(() =>
{
Thread.Sleep(4000);
return 3;
});
Task.Factory.ContinueWhenAny(new[] {t1, t2,t3}, (t) =>
{
Console.WriteLine(t.Result);
});
Run Code Online (Sandbox Code Playgroud)
此代码启动3个任务,并等待其中一个完成.因为t22秒后抛出异常,所以它是可用的ContinueWhenAny.
从上面的代码我想得到3 t.Result.
是否有选项只在任务成功完成后继续?就像是Task.Factory.ContinueWhenAnyButSkipFailedTasks
编辑1 这是我现在基于@Nitram答案的解决方案:
var t1 = Task.Factory.StartNew(() =>
{
var rnd = new Random();
Thread.Sleep(rnd.Next(5,15)*1000);
throw new Exception("My error");
return 1;
});
var …Run Code Online (Sandbox Code Playgroud) 我在我的asp.net web api 2应用程序中使用HttpClient类将一些信息发布到端点.我只是想在不等待回复的情况下发布信息.这是正确的语法
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:9000/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// HTTP POST
var gizmo = new Product() { Name = "Gizmo", Price = 100, Category = "Widget" };
var response = await client.PostAsJsonAsync("api/products", gizmo);
}
Run Code Online (Sandbox Code Playgroud) 我有一个Controller Action方法来保存用户详细信息,如下所示。
public async Task<ActionResult> SaveUser(ViewModel.VM_CreateUser user)
{
var result = await _user.Save(userDetails);
return Json(new { Success = String.IsNullOrEmpty(result) });
}
Run Code Online (Sandbox Code Playgroud)
到目前为止,以上四行功能都没有问题。
public async Task<ActionResult> SaveUser(ViewModel.VM_CreateUser user)
{
var result = await _user.Save(userDetails);
new MailController().CreateUser(user.userDetails); //<==This is problem line of code.
}
Run Code Online (Sandbox Code Playgroud)
下面是我的邮件控制器。
public class MailController : MailerBase
{
public void CreateUser(ViewModel.VM_User user)
{
To.Add(user.EmailAddress);
From = System.Configuration.ConfigurationManager.AppSettings["emailSender"];
Subject = "Hi";
Email("CreateUser", user).DeliverAsync();
}
}
Run Code Online (Sandbox Code Playgroud)
在上面的代码中,执行电子邮件发送代码时遇到问题。我收到以下错误消息。
异步模块或处理程序在异步操作仍挂起的同时完成
请提出纠正措施!