在异步方法并行任务中【SqlSugarScope】报错,这个不是线程安全的么? 返回

SqlSugar
7 327
伪代码修改了一下,这里的update需要调用一些异步方法,所以需要声明async,还有ForEach中的task.run是希望对于每个model可以做异步并行处理,所以此处不希望使用await task.run


static void Main(string[] args)
        {
                scope = new SqlSugarScope(new ConnectionConfig
                        {
                            IsAutoCloseConnection = true,
                            DbType = DbType.MySql,
                            ConnectionString = "*****"
                        });
        
            Update();

            Console.ReadLine();
        }

        static async Task Update()
        {
            await other_func_async();
            scope.Queryable<TestModel>()
            .ToList()
            .ForEach(model =>
            {
                Task.Run(async () =>
                {
                    try
                    {
                         await the_task_other_func();
                         model.status = 1;
                        int isOk = await scope.Saveable(model).ExecuteCommandAsync();
                        logger.Info($"UpdateResult:{isOk}");
                    }
                    catch (Exception ex)
                    {
                        logger.Error($"UpdateError:{ex}");
                    }
                });
            });
            await other_func_async2();
        }


错误如下:


日志内容:UpdateError:SqlSugar.SqlSugarException: 中文提示 :  连接数据库过程中发

生错误,检查服务器是否正常连接字符串是否正确,实在找不到原因请先Google错误信息:

There is already an open DataReader associated with this Connection which must

e closed first..

English Message : Connection open error . There is already an open DataReader a

sociated with this Connection which must be closed first.

   at SqlSugar.AdoProvider.GetDataReader(String sql, SugarParameter[] parameter

)

   at SqlSugar.QueryableProvider`1.GetData[TResult](KeyValuePair`2 sqlObj)

   at SqlSugar.QueryableProvider`1._ToList[TResult]()

   at SqlSugar.QueryableProvider`1.ToList()

   at SqlSugar.SaveableProvider`1.get_insertObjects()

   at SqlSugar.SaveableProvider`1.LoadInsertable()

   at SqlSugar.SaveableProvider`1.ExecuteCommand()

   at SqlSugar.SaveableProvider`1.ExecuteCommandAsync()

   at SqlSugarDemo2.Program.<>c__DisplayClass4_0.<<Update>b__1>d.MoveNext()


热忱回答7

  • SqlSugarScope的初始化放在Main中也是一样报错。

    这里当Update函数声明为async就会报错,去掉async并将await Task.CompletedTask 改为 return Task.CompletedTask则功能正常,但在业务中该函数中有其他异步业务调用所以需声明为async异步操作

    0 回复
  • fate sta fate sta VIP0
    2022/1/17

    没有await就不要用异步,正确代码如下:

    using SqlSugar;
    using System;
    using System.Threading.Tasks;
    
    namespace OrmTest
    {
        class Program
        {
            static void Main(string[] args)
            {
                //for (int i = 0; i < 100; i++)
                //{
                //    Demo3_Insertable.Init(); 
                //}
                Update().GetAwaiter().GetResult();
    
                Console.ReadLine();
            }
    
            static async Task Update()
            {
               var scope = new SqlSugarScope(new ConnectionConfig
                {
                    IsAutoCloseConnection = true,
                    DbType = DbType.MySql,
                    ConnectionString =Config.ConnectionString
                });
                var list = scope.Queryable<Order>()
                .ToList();
                foreach (var model in list)
                {
                    await Task.Run(async () =>
                    {
                        try
                        {
    
                            int isOk = await scope.Saveable(model).ExecuteCommandAsync();
                            Console.WriteLine(model.Id);
    
                        }
                        catch (Exception ex)
                        {
               
                        }
                    });
                }
               
            }
    
    
        }
    }


    0 回复
  • fate sta fate sta VIP0
    2022/1/17

    虽然是线程安全不过你异步乱用还是可能会出错的

    0 回复
  • @fate sta在业务中该函数中有其他异步业务调用所以需声明为async异步操作,这里await Task.CompletedTask;其实就是调用其他异步方法的替代,只是为了展示,其实你可以当我这里是await other_func(); 

    还有就是Task.Run这里我是希望可以并行处理的所以不能用await阻塞,因为包含一些其他的业务操作,业务操作完之后才会Saveable(model).ExecuteCommandAsync

    0 回复
  • fate sta fate sta VIP0
    2022/1/17

    @Restraint: https://www.donet5.com/Home/Doc?typeId=2349  异步有异步用法

    0 回复
  • @fate sta:这里的异步方式我看过了,

    1. 此处使用的是SqlSugarClient而不是SqlSugarScope,所以需要自己在相关的task中new SqlSugarClient

    2. 这个示例中的不一样的在于tolist使用tolistasync,这里的异步区别不大,使用后依然报错,对于下面不一样在于task.whenall,这里是为了等待所有子任务完成从而进行后续操作,而我这里每个task之间互不影响,后续操作并不依赖所有task结束,而且接入whenall报错依旧


    综上结论,感觉这里的问题可能在于SqlSugarScope对于task的支持有限,也可能是其他我没有发现的点位有问题

    0 回复
  • fate sta fate sta VIP0
    2022/1/17

    @Restraint:底层驱动就这样和sqlsugarscope并没关系,TaskWhenAll里面的东西没办法去处理,所以只能new , 像sqlserver这块就支持非常好不需要new就能taskwhenall

    0 回复