- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章ASP.NET 谨用 async/await由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
C# 5.0 引入 async/await 关键字,旨在简化异步编程模型,抛去语法糖就是 Net4.0 的 Task + 状态机。其实在处理异步编程使用 Task 还是挺简单的,不过既然推出了新的语法糖,难免会尝试一下,然而在使用中却没想象中那么单纯。以下针对ASP.NET 应用程序实际使用过程中的一些总结, 包括 异常捕获 、 死锁 、 应用程序崩溃 ,实际使用过程中一不注意就可能掉坑里了.
异常捕获 。
async 方法有三种返回类型: void、Task、Task 。
async void 。
该方式声明的方法是无法使用 catch 捕获异常的,所以以下代码的 try、catch 并没什么卵用.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
private
static
async
void
ThrowExceptionAsync()
{
await Task.Delay(1000);
throw
new
Exception(
"抛个异常玩玩"
);
}
public
static
async
void
CatchAsyncVoidException()
{
try
{
ThrowExceptionAsync();
}
catch
(Exception ex)
{
throw
ex;
}
}
|
async Task 或 async Task 。
这两种方式声明的方法异常信息会包含Task属性内,但前提需要在try里面使用 await 等待.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
private
static
async Task ThrowExceptionAsync()
{
await Task.Delay(1000);
throw
new
Exception(
"抛个异常玩玩"
);
}
public
static
async Task CatchAsyncTaskException()
{
try
{
await ThrowExceptionAsync();
}
catch
(Exception ex)
{
throw
ex;
}
}
TaskScheduler.UnobservedTaskException
|
未捕获的 Task 异常信息可以通过设置全局的TaskScheduler.UnobservedTaskException 来记录错误日志,在 Global.asax 增加如下代码:
1
2
3
4
5
6
7
8
9
10
11
12
|
void
Application_Start(
object
sender, EventArgs e)
{
// 在应用程序启动时运行的代码
TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskExceptionException;
}
void
TaskScheduler_UnobservedTaskExceptionException(
object
sender, UnobservedTaskExceptionEventArgs e)
{
if
(e.Exception !=
null
)
{
// do something
}
}
|
同步上下文 。
异步编程必然是关于线程的使用,线程有一个同步上下文的概念,个人认为线程同步上下文是 async/await 遇到最揪心的问题。在现有项目开发中我们可能想尝试使用 async/await,但老代码都是同步方式,这时如果调用一个声明为 async 的方法,死锁和应用程序崩溃的问题一不小心就可能出现.
注意:控制台程序和.Net Core程序 将不会遇到这个问题,它们不需要同步上下文.
死锁 。
1
2
3
4
5
6
7
8
9
10
|
private
static
async Task XXXAsync()
{
await Task.Delay(1000);
// some code
}
public
static
void
Test()
{
var task = XXXAsync();
task.Wait();
}
|
以上代码很完美的实现了死锁。 默认情况下,当 Wait() 未完成的 Task 时,会捕获当前线程上下文,在 Task 完成时使用该上下文恢复方法的执行。 当 async 方法内的 await 执行完成时,它会尝试获取调用者线程所在的上下文执行方法的剩余部分, 但是该上下文已含有一个线程,该线程在等待 async 方法完成。然后它们相互等待对方,然后就没有然后了,死在那里.
针对死锁问题的解决方式是增加 ConfigureAwait(false) 。
1
2
|
// await Task.Delay(1000);
await Task.Delay(1000).ConfigureAwait(
false
);
// 解决死锁
|
当 await 等待完成时,它会尝试在线程池上下文中执行 async 方法的剩余部分,因此就不存在死锁.
应用程序崩溃 。
测试环境总发现IIS应用程序池总是崩溃,到底是什么原因?当时我们对这个问题也是非常懵逼,代码看上去并没什么明显毛病,试图欺骗自己应该是环境本身的问题吧,但事实上确实是在代码中下了毒。通过各种资料查阅和测试,基本可以断定是同步代码调用异步代码,同步上下文引起的问题.
如果调用一个 async 方法。如果使用 await 等待,当前线程立马被释放回线程池,线程的上下文信息会被保存。如果没有使用 await(async void 的方法,必然没有办法使用 await),调用 async 方法之后,代码会继续往下执行,执行完成后当前线程被释放回线程池,线程的上下文信息不会被保存。当 async 中的异步任务执行完成后,会从线程池中获取一个线程继续执行剩余代码,同时会获取当初调用者所在线程的上下文信息(如果当初调用者所在线程没有释放回线程池,上下文信息可以获取到)。那么问题就来了,如果当初调用者没有使用 await 并且 所在线程释放回线程池了,上下文信息因为没有被保持下来,就获取不到了,这时候会抛出异常 未将对象引用设置到对象的实例 ,经过测试这个异常信息并不一定每次都会出现,原因和线程的释放有关,调用者所在线程的上下文信息存在就不会抛出异常。异常错误信息如下,这个异常最终会导致应用程序集停止.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
在 System.Web.ThreadContext.AssociateWithCurrentThread(Boolean setImpersonationContext)
在 System.Web.HttpApplication.OnThreadEnterPrivate(Boolean setImpersonationContext)
在 System.Web.LegacyAspNetSynchronizationContext.CallCallbackPossiblyUnderLock(SendOrPostCallback callback, Object state)
在 System.Web.LegacyAspNetSynchronizationContext.CallCallback(SendOrPostCallback callback, Object state)
在 System.Web.LegacyAspNetSynchronizationContext.Post(SendOrPostCallback callback, Object state)
在 System.Threading.Tasks.SynchronizationContextAwaitTaskContinuation.PostAction(Object state)
在 System.Threading.Tasks.AwaitTaskContinuation.RunCallback(ContextCallback callback, Object state, Task& currentTask)
--- 引发异常的上一位置中堆栈跟踪的末尾 ---
在 System.Threading.Tasks.AwaitTaskContinuation.<>c.<ThrowAsyncIfNecessary>b__18_0(Object s)
在 System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(Object state)
在 System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
在 System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
在 System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
在 System.Threading.ThreadPoolWorkQueue.Dispatch()
在 System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()
|
针对以上异常我们有什么方式可以解决呢?依然是ConfigureAwait(false),在 Task 上加上 ConfigureAwait(false),此设置代表当 async 中的异步任务完成后,不读取当时调用它的原线程的上下文信息,而是在线程池上下文中执行 async 方法的剩余部分.
1
2
3
4
5
6
7
|
public
static
Task XXXAsync()
{
await Task.Run(() =>
{
// some code
}).ConfigureAwait(
false
);
}
|
总结 。
以上所述是小编给大家介绍的ASP.NET 谨用 async/await,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我网站的支持! 。
原文链接:http://beckjin.com/2018/01/07/aspnet-async-await/?utm_source=tuicool&utm_medium=referral 。
最后此篇关于ASP.NET 谨用 async/await的文章就讲到这里了,如果你想了解更多关于ASP.NET 谨用 async/await的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我试图对 ASP.Net MVC 有一个高层次的理解,我开始意识到它看起来很像原始的 ASP 脚本。过去,我们将“模型”/业务逻辑代码组织到 VBScript 类或 VB COM 组件中。 当然,现在
我已经搜索了一段时间,但似乎找不到答案。 我想在我的旋转木马中显示一个计数器,左边是当前项目(工作),左边是项目总数。 我的代码:
. 最佳答案 Scott Gu 称这些为代码块。这就是我的看法。 http://weblogs.asp.net/scottgu/archive/2010/04/06/new-lt-gt-syntax
我有一个使用 Visual Studio 2010/.net 4/VB 制作的网站。 我真的很喜欢我发现的 FAQ 系统的布局,因为它很简单,但它是经典的 asp。所以,显然,我不能包括我的母版页布局
好吧,对于你们许多人来说,这个问题可能有一个非常明显的答案,但它让我难住了。 我有一个 asp.net Web 表单,上面有两个控件(嗯,不止这两个,但我们将重点关注这些) - 第一个是 asp:dr
当我将 ASP.NET 复选框控件设置为 asp.net 更新面板的异步回发触发器时,EventName 属性是什么? 最佳答案 我相信它是 CheckedChanged。 关于asp.net - a
我有一个用经典 asp 编写的(巨大的)网站。现在我必须切换到 vb.net (razor)。有没有办法将这两个结合起来直到切换完成? 有没有办法让应用程序与经典的 asp 和 vb.net 一起工作
I am creating a products page, where the user selects an option in a radiobuttonlist for example, an
我最近将一个经典的 ASP 应用程序转换为 ASP.NET 3.5,但我觉得我的经典 ASP 版本要快一些(我不知道可能买家会后悔)。 所以你们能帮我解决这个问题吗,让我知道哪个更快,asp、asp.
从本周开始,我被要求开始学习如何使用 ASP 开发网站。我通过 XNA 对 C# 有一定的经验,所以这部分对我来说并不是什么麻烦。 我一直在关注Music Store Tutorial这需要我设置一个
关闭。这个问题需要多问focused 。目前不接受答案。 想要改进此问题吗?更新问题,使其仅关注一个问题 editing this post . 已关闭 8 年前。 Improve this ques
我想将一些表单变量发布到经典 ASP 页面中。我不想改变经典的 ASP 页面,因为需要完成大量的工作,以及消耗它们的页面数量。 经典的 ASP 页面需要将表单变量 Username 和 Userpas
已结束。此问题正在寻求书籍、工具、软件库等的推荐。它不满足Stack Overflow guidelines 。目前不接受答案。 我们不允许提出寻求书籍、工具、软件库等推荐的问题。您可以编辑问题,以便
在某种程度上,这可能是一个异端问题。我们有一个大型站点,其中许多页面仍在ASP中。通常,并没有真正动态的,而是包括(通过SSI或Server.Execute)定期重新生成的HTML块。看起来好像是一个
关闭。这个问题需要多问focused 。目前不接受答案。 想要改进此问题吗?更新问题,使其仅关注一个问题 editing this post . 已关闭 9 年前。 Improve this ques
我有一个遗留的 ASP 应用程序——在不久的某个时候——需要迁移到 ASP.Net 2.0(以与也在 2.0 中的其他应用程序兼容)。 对于这类事情是否有最佳实践,即作为第一步将当前 html、vbs
我目前在一家公司工作,该公司使用 ASP.NET Webforms 和旧 ASP 页面的组合进行 Web 开发。这对于他们当前的项目来说效果很好,但我想说服/建议他们切换到 ASP.NET MVC,因
我有一个经典的 asp 应用程序。我想将该页面的竞赛表格发布到 Asp.Net 表格。原因是我想在进入数据库之前使用我在 Asp.Net 页面中内置的大量逻辑进行验证,而我对 asp 不太了解。更不用
我知道在 ASP.NET MVC 中,您可以拥有移动 View 并执行类似 Index.mobile.cshtml 的操作。和 _Layout.mobile.cshtml并且服务器知道将这些 View
我需要从一些服务器端 c#.net 代码中调用经典 asp 页面上的 VBscript 函数 - 有谁知道一种干净的方法来做到这一点?在 .net 中重写函数不是一种选择。 我会再解释一下这个问题..
我是一名优秀的程序员,十分优秀!