Home Best way to fire and forget async code inside TransactionScope
 I'm doing some stuff inside a using block for a TransactionScope object. At some point I wanted to call some async code by firing and forget (I don't want to wait for the result, and I'm not interested in what happens during that call) and I wanted that code to not be part of the transaction (by using TransactionScopeOption.Suppress option). So initially I made something similar to the methodFails that I have commented in the code below. It got me a nice "System.InvalidOperationException: 'TransactionScope nested incorrectly'". I looked up in SO for somebody having similar problems, and found this Question where the answer by ZunTzu gave me the idea for method1 using TransactionScopeAsyncFlowOption.Enabled option, which works as I expected for methodFails but without the exception. Then I thought of an alternative that I put in method2 that consists in putting the async code in a third method (method3) called by firing-and-forget while the TransactionScopeOption.Suppress option is kept in the non-async method2. And this approach seems to work as good as method1 in my sample program. So my question is: which approach is better, method1 or method2, or maybe a third one that I have no thought about? I'm leaning for method1 because it sounds like "the people making the TransactionScope class put that TransactionScopeAsyncFlowOption there for a reason". But the fact that TransactionScopeAsyncFlowOption.Enabled is not the default for a TransactionScope makes me think that maybe there is a performance hit by enabling that, and fire-and-forget may be a special case where I can save that performance hit. The sample code:  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!!"); } }