TransactionScope 与 Async/Await
你可能不知道这一点,在 .NET Framework 4.5.0 版本中包含有一个关于 System.Transactions.TransactionScope 在与 async/await 一起工作时会产生的一个严重的 bug 。由于这个错误,TransactionScope 不能在异步代码中正常操作,它可能更改事务的线程上下文,导致在处理事务作用域时抛出异常。
这是一个很大的问题,因为它使得涉及事务的异步代码极易出错。
好消息是,在 .NET Framework 4.5.1 版本中,微软发布了这个 "异步连接" 错误的修复程序。作为开发者的我们需要明确的做到以下两点:
- 如果说你在 TransactionScope 代码中使用 async/await,你需要将框架升级到 .NET 4.5.1 或以上版本。
- 在有包装异步代码的 TransactionScope 的构造函数中指定
TransactionScopeAsyncFlowOption.Enabled .
TransactionScope
System.Transactions.TransactionScope 类允许我们在事务中包装数据库代码,基础结构代码,有时甚至包括第三方代码(如果第三方库支持)。 然后,代码只在我们实际想提交(或完成)事务时才执行操作。
只要 TransactionScope 中的所有代码都在同一线程上执行,调用堆栈上的所有代码都可以与代码中定义的 TransactionScope 一起参与。 我们可以在父事务作用域内嵌套作用域或创建新的独立作用域。 我们甚至可以创建 TransactionScope 的副本,并将副本传递到另一个线程并连接回调用线程。 通过使用事务作用域包装代码,使用隐式事务模型,也称为环境事务。
如下代码:
![](/assets/blank.gif)
public void TransactionScopeAffectsCurrentTransaction() {Debug.Assert(Transaction.Current == null);using (var tx = new TransactionScope()) {Debug.Assert(Transaction.Current != null);SomeMethodInTheCallStack();tx.Complete();}Debug.Assert(Transaction.Current == null); }private static void SomeMethodInTheCallStack() {Debug.Assert(Transaction.Current != null); }
![](/assets/blank.gif)
正如我们可以看到使用块外面的 Transaction.Current 属性为 null。 在使用块内 Transaction.Current 属性不为 null。 即使在调用堆栈中的方法像 SomeMethodInTheCallStack 可以访问 Transaction.Current,前提是它要被包裹在使用块中。
TransactionScope 的好处是,如果需要,本地事务自动升级到分布式事务。 事务范围还简化了对事务的编程,如果你喜欢隐式的显式。
TransactionFlowInterruptedException
当 async / await 引入了 C#5.0 和 .NET 4.5,一个小小的细节被完全忘记。 当在一个包装 TransactionScope 下调用一个异步方法时,编译器引入的底层状态机没有正确地“浮动”事务(原文 "float")。 让我们将我们关于 TransactionScope 如何在同步代码中工作的知识应用到异步代码。
有如下代码:
![](/assets/blank.gif)
public async Task TransactionScopeWhichDoesntBehaveLikeYouThinkItShould() {using (var tx = new TransactionScope()){await SomeMethodInTheCallStackAsync().ConfigureAwait(false);tx.Complete();} }private static async Task SomeMethodInTheCallStackAsync() {await Task.Delay(500).ConfigureAwait(false); }
![](/assets/blank.gif)
不幸的是,它不工作的方式。 代码几乎(但只是几乎)执行类似于同步版本,但如果项目这个代码是写在目标 .NET Framework 4.5,当我们到达使用块的结束,并尝试处置 TransactionScope 时抛出以下异常 :
System.InvalidOperationException:一个 TransactionScope 必须处理在它被创建的同一个线程。
为了使TransactionScope和async正常工作,我们需要将我们的项目升级到.NET 4.5.1。
TransactionScopeAsyncFlowOption
在 .NET 4.5.1中,TransactionScope 有一个名为 TransactionScopeAsyncFlowOption 的新枚举,可以在构造函数中提供。 您必须通过指定,明确地选择跨线程连续的事务流,如下:
![](/assets/blank.gif)
using (var tx = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) {await SomeMethodInTheCallStackAsync().ConfigureAwait(false);tx.Complete(); }
![](/assets/blank.gif)
你可能很好奇,默认的 TransactionScopeAsyncFlowOption 是 Suppress(阻止的),因为微软想避免破坏 .NET 4.5.0 版本中代码库中行为。
最后
使用 TransactionScope 结合 async / await 时,你应该更新所有使用 TransactionScope 的代码路径以启用 TransactionScopeAsyncFlowOption.Enabled 。 这样才能使事务能够正确地流入异步代码,防止在TransactionScope下使用时业务逻辑不正常。
英文原文:TransactionScope and Async/Await. Be one with the flow!
原文地址:https://www.cnblogs.com/god--love-you/p/6076265.html
转载于:https://www.cnblogs.com/hzz521/p/9598952.html
TransactionScope 与 Async/Await相关推荐
- setTimeout、setInterval、promise、async/await的顺序详解(多种情况,非常详细~)
本文很长,列举的情况很多. 在阅读本文之前,如果您有充足的时间,请新建一个项目与本文一同实践. 每段代码都有对应的解释,但是自己动手尝试印象才会更深哦~ setInterval:表示多久执行一次,需要 ...
- C# async await 学习笔记2
C# async await 学习笔记1(http://www.cnblogs.com/siso/p/3691059.html) 提到了ThreadId是一样的,突然想到在WinForm中,非UI线程 ...
- promise 和 async await区别
什么是Async/Await? async/await是写异步代码的新方式,以前的方法有回调函数和Promise. async/await是基于Promise实现的,它不能用于普通的回调函数. as ...
- angular2 学习笔记 ( Rxjs, Promise, Async/Await 的区别 )
Promise 是 ES 6 Async/Await 是 ES 7 Rxjs 是一个 js 库 在使用 angular 时,你会经常看见这 3 个东西. 它们都和异步编程有关,有些情况下你会觉得用它们 ...
- async await:比requests 更强大
最近公司 Python 后端项目进行重构,整个后端逻辑基本都变更为采用"异步"协程的方式实现.看着满屏幕经过 async await(协程在 Python 中的实现)修饰的代码,我 ...
- @async 默认线程池_.NET Web应用中为什么要使用async/await异步编程?
布莱恩特:.NET Core开发精选文章目录,持续更新,欢迎投稿!zhuanlan.zhihu.com 前言 1.什么是async/await? await和async是.NET Framework ...
- Atitit. Async await 优缺点 异步编程的原理and实现 java c# php
Atitit. Async await 优缺点 异步编程的原理and实现 java c# php 1. async & await的来源1 2. 异步编程history1 2.1. 线程池 2 ...
- 8张图让你一步步看清 async/await 和 promise 的执行顺序
2019独角兽企业重金招聘Python工程师标准>>> **摘要:**面试必问 原文:8张图帮你一步步看清 async/await 和 promise 的执行顺序 作者:ziwei3 ...
- 用 async/await 来处理异步
引用出处:https://www.cnblogs.com/SamWeb/p/8417940.html 昨天看了一篇vue的教程,作者用async/ await来发送异步请求,从服务端获取数据,代码很简 ...
最新文章
- 机器学习:特征选择和降维实例
- mysql5.6安装sys库_MySQL5.6数据库优化my.cnf配置
- GitHub的10,000个最受欢迎的Java项目-以下是它们使用的顶级库
- 输入一个正整数n,计算s=1-1/3+1/5-1/7…前n项之和
- 换行与回车(\r \n)的起源以及在编制语言中的使用
- 【渝粤教育】广东开放大学 生产与运作管理 形成性考核 (36)
- python合并单元格居中_Python实现Excel自动分组合并单元格
- PHP:同时发送多个异步ajax请求,但数据却是按同步顺序返回
- 百度浏览器内核太低,浏览京东有问题
- 顶级区块链开发人员工具:涉及框架、IDE、安全工具、测试网络、区块链预言机和节点服务
- 【第三方互联】微博2、创建新浪微博(sina)互联应用
- Centos8关闭防火墙
- Android Hal层回调APP应用接口
- base64编码解码讲解
- restore,recover的区别
- 计算机一级比分多少,如何在电子表格中打出比分?
- 计算股票季度收益率、年收益率和相对收益率并可视化展示。
- 全国信息竞赛语言有python吗_2019年全国信息学竞赛有哪些
- 安卓android按宽/高缩放图片到指定大小并进行裁剪得到中间部分图片
- k8s-重启kubelet服务异常 kubelet.service: main process exited, code=exited, status=1/FAILURE