需要满足下面2条
1、 你想要最快的执行完,并且不在乎短期占用太多资源,能保证线程安全(比Task.Run 性能更快,也不需要考虑线程安全)
2、 数据库操作10个以上,如果只有几个数据库操作就没必要用了和一般的异步没多少区别
注意:每种数据库用法不一样
Task并行执行数量在100以下为佳,如果超过100需要设置max pool size=1000,
并且建议并行执行一次不要超1000 (如果是SqlServer用法2性能更好)
var ts = new List<Task>(); for (int i = 0; i < 1000; i++)//建议一次执行Task不工 { //需要CopyNew()强制new出新对象,因为AsyncLocal没办法区分异步上下文 ts.Add(db.CopyNew().Queryable<Order>().FirstAsync()); } await Task.WhenAll(ts); //如果用db.CopyNew().XXX.ToListAsync()这种不需要包Task.Run //db.ThenMapper异步并发需要这样处理 var ts = new List<Task>(); for (int i = 0; i < 1000; i++)//建议一次执行Task不工 { var newDb=db.CopyNew(); var list=await newDb.Queryable....; ts.Add(newDb.ThenMapperAsync...) } await Task.WhenAll(ts);
注意:1、异步方法 Task.WhenAll
2、db是同一个,并且用事务
3、SqlServer需要连接字符串加上 MultipleActiveResultSets=True
4、Thenmapper 要按标题1来实现
下面是一个完整的用例并且测试通过
using System.Linq; using System.Threading.Tasks; namespace OrmTest { class Program { static async Task Main(string[] args) { int max = 1000; Task[] tasks = new Task[max]; var db = GetClient();//db需要是同一个 db.BeginTran(); //强制关闭自动释放(如果手动释放可以不用事务) for (int i = 0; i < max; i++) { //如果是SqlSugarScope禁止出现Task.Run //原因:有Task.Run SqlSugarScope异步上下文会变事务会有问题 tasks[i]=db.Queryable<Order>() .Take(10) .ToListAsync();//直接等于ORM异步方法 } await Task.WhenAll(tasks); db.CommitTran(); //关闭数据库 } private static SqlSugarClient GetClient() //SqlSugarClient和SqlSugarScope都行 { return new SqlSugarClient(new ConnectionConfig() { DbType = SqlSugar.DbType.SqlServer, //SqlServer Sqlite Oracle //注意配置 ConnectionString = OrmTest.Config.ConnectionString, IsAutoCloseConnection = true, AopEvents = new AopEvents { OnLogExecuting = (sql, p) => { Console.WriteLine(sql); Console.WriteLine(string.Join(",", p?. Select(it => it.ParameterName + ":" + it.Value))); } } }); } } }
测试结果
本身IIS就是多线程操作,所以不是特殊需求没必要并发查询,并发查询会把数据库的IO充份利用,并且可以保证线程安全,
配置 1165G7 SSD | 结果 |
Task.WhenAll | 1000个1秒 |
Task.Run(()=>{ var db=new sqlsugarclient(); db.xxx}) | 1000就10秒 |
2016 © donet5.comApache Licence 2.0