我正在为 TransactionScope 对象的 using 块内做一些事情。在某些时候,我想通过触发并忘记来调用一些异步代码(我不想等待结果,而且我对该调用期间发生的事情不感兴趣)并且我希望该代码不属于交易(通过使用TransactionScopeOption.Suppress
选项)。
所以最初我做了一些类似于methodFails
我在下面的代码中评论过的东西。它给了我一个很好的"System.InvalidOperationException: 'TransactionScope nested wrong'"。我在 SO 中查找有类似问题的人,并找到了这个问题,其中 ZunTzu 的答案给了我method1
使用TransactionScopeAsyncFlowOption.Enabled
选项的想法,它按我的预期工作,methodFails
但没有例外。
然后我想到了一个替代方案,method2
即把异步代码放在第三种方法(method3
)中,该方法由触发和忘记调用,而TransactionScopeOption.Suppress
选项保留在非异步method2
中。这种方法似乎和我的示例程序一样好用method1
。
所以我的问题是:哪种方法更好,method1
或者method2
,或者可能是我没想过的第三种方法?我倾向于method1
因为这听起来像“制作 TransactionScope 类的人将 TransactionScopeAsyncFlowOption 放在那里是有原因的”。但是事实上这TransactionScopeAsyncFlowOption.Enabled
不是 TransactionScope 的默认设置,这让我认为启用它可能会影响性能,而即发即弃可能是我可以保存该性能影响的一种特殊情况。
示例代码:
class Program
{
static void Main(string[] args)
{
using (TransactionScope scope1 = new TransactionScope())
{
// Do some stuff in scope1...
// Start calls that could execute async code
//Task a = methodFails(); // This commented method would launch exception: System.InvalidOperationException: 'TransactionScope nested incorrectly'
Task b = method1(); // Fire and forget
method2();
// Rest of stuff in scope1 ...
}
Console.ReadLine();
}
static async Task methodFails()
{
//Start of non-transactional section
using (TransactionScope scope2 = new TransactionScope(TransactionScopeOption.Suppress))
{
//Do non-transactional work here
Console.WriteLine("Hello World 0.1!!");
await Task.Delay(10000);
Console.WriteLine("Hello World 0.2!!");
}
//Restores ambient transaction here
Console.WriteLine("Hello World 0.3!!");
}
static async Task method1()
{
//Start of non-transactional section
using (TransactionScope scope2 = new TransactionScope(TransactionScopeOption.Suppress, TransactionScopeAsyncFlowOption.Enabled))
{
//Do non-transactional work here
Console.WriteLine("Hello World 1.1!!");
await Task.Delay(10000);
Console.WriteLine("Hello World 1.2!!");
}
//Restores ambient transaction here
Console.WriteLine("Hello World 1.3!!");
}
static void method2()
{
//Start of non-transactional section
using (TransactionScope scope2 = new TransactionScope(TransactionScopeOption.Suppress))
{
//Do non-transactional work here
Task ignored = method3(); // Fire and forget
}
//Restores ambient transaction here
Console.WriteLine("Hello World 2.2!!");
}
static async Task method3()
{
//Do non-transactional work here
Console.WriteLine("Hello World 2.1!!");
await Task.Delay(10000);
Console.WriteLine("Hello World 2.3!!");
}
}