在开发异步的WebApi时,发现一个线程并发错误,起初以为SqlSugar问题。后来,经查是代码写的问题。但此问题,不遇到,不会知晓,只有异步才会出现此问题。
这种问题,也发生在JavaScript下,代码逻辑是一样的。参看这篇:https://advancedweb.hu/how-to-use-async-functions-with-array-foreach-in-javascript/
一般同步模式,ForEach会对每个元素同步执行,上一个执行完成才执行下一个。List.ForEach(x=>{
Do(x);
});
但是,异步模式不是这样,对每个元素不等待执行完成,会进入下个一元素。如果Do内操作数据库,这会造成多线程相关错误。List.ForEach(async x=>{
await Do(x);
});
这时,可以用foreach(var x in List){ await Do(x); } 此模式会对List元素一个一个同步执行。
相关代码,我做了个样例,.Net 7控制台:
1 /*第一种模式 ForEach内部,每个循环,不等待上一步完成,一起执行*/ 2 /* 3 * Expected output: 4 Item:1 Before. Thread:1 5 Item:2 Before. Thread:1 6 Item:3 Before. Thread:1 7 Finish. Thread:1 8 Do:3 Thread:9 9 Item:3 After. Thread:9 10 Do:2 Thread:9 11 Item:2 After. Thread:9 12 Do:1 Thread:9 13 Item:1 After. Thread:9 14 */ 15 //new int[] { 1, 2, 3 }.ToList().ForEach(async x => 16 //{ 17 // Console.WriteLine($"Item:{x} Before. Thread:{Thread.CurrentThread.ManagedThreadId}"); 18 // await A.Do(x); 19 // Console.WriteLine($"Item:{x} After. Thread:{Thread.CurrentThread.ManagedThreadId}"); 20 //}); 21 22 /*第二种模式 foreach内部,每个循环,等待上一步完成,同步执行*/ 23 /* 24 * Expected output: 25 Item:1 Before. Thread:1 26 Do:1 Thread:4 27 Item:1 After. Thread:4 28 Item:2 Before. Thread:4 29 Do:2 Thread:4 30 Item:2 After. Thread:4 31 Item:3 Before. Thread:4 32 Do:3 Thread:4 33 Item:3 After. Thread:4 34 Finish. Thread:4 35 */ 36 foreach (var x in new int[] { 1, 2, 3 }) 37 { 38 Console.WriteLine($"Item:{x} Before. Thread:{Thread.CurrentThread.ManagedThreadId}"); 39 await A.Do(x); 40 Console.WriteLine($"Item:{x} After. Thread:{Thread.CurrentThread.ManagedThreadId}"); 41 42 } 43 44 Console.WriteLine($"Finish. Thread:{Thread.CurrentThread.ManagedThreadId}"); 45 Console.ReadKey(); 46 47 class A 48 { 49 50 public static async Task Do(int a) 51 { 52 await Task.Delay((10 - a) * 1000); 53 Console.WriteLine($"Do:{a} Thread:{Thread.CurrentThread.ManagedThreadId}"); 54 } 55 }
标签:Do,After,Console,Thread,Await,List,Item,ForEach,Before From: https://www.cnblogs.com/wigis/p/17745737.html