C#多线程任务处理

开发过程中,有时因为业务需求,需要我们执行完成正常的业务逻辑之后,再去做一些不影响主业务流程的操作。当我们的主流程已经完成了,没必要关注之后进行的操作的返回结果,这时我们就可以尝试开启一个新的线程来帮我们完成这个需求,让当前的线程不必因此而停滞等候。

1、Task.Run()的使用:

········public WebApiResult TestService()
        {
            var result = new WebApiResult();
            try
            {
                // 执行主要业务流程,假设删除一条数据
                Console.WriteLine("主要流程执行结束;");
                // 调用外部接口通知某条数据已被删除,将此消息推送到消息队列
                Task.Run(() => this.PushService());
            }
            catch (Exception ex)
            {
                result.AddError(this.GetException(ex));
            }
            return result;
        }

        public void PushService()
        {
            // 推送消息队列
            // 此处不做详细介绍,感兴趣可自行百度消息队列的使用
        }

        public virtual string GetException(Exception ex)
        {
            var s = ex.Message;
            if (ex.InnerException != null)
            {
                return s + "\n" + GetInnerException(ex.InnerException);
            }
            return s;
        }

注:如果异步调用的方法中需要对数据库进行操作,需要开启一个新的数据库连接事务 

 2、借助Parallel.For()及 Parallel.ForEach()进行异步处理:

        public WebApiResult<AdjustPriceDetailModel> GetAdjustPriceDetail(string adjustPriceId)
        {
            var result = new WebApiResult<AdjustPriceDetailModel>();
            try
            {
                int count = 10;
                List<string> list = new List<string>();
                // 异步for循环,数据量大的情况下可加快执行效率
                // 千万不要在次循环中往公用的集合中添加值,存在数据被覆盖的情况
                Parallel.For(0, count, t =>
                {
                    var num = t + 1;
                    //log.Info(num);
                    list.Add($"第{num}条数据");
                });
                log.Info($"输出:{JsonConvert.SerializeObject(list)}");
            }
            catch (Exception ex)
            {
                result.AddError(this.GetException(ex));
            }
            return result;
        }

错误示范:

        public WebApiResult<AdjustPriceDetailModel> GetAdjustPriceDetail(string adjustPriceId)
        {
            var result = new WebApiResult<AdjustPriceDetailModel>();
            try
            {
                int count = 10000;
                List<string> list = new List<string>();
                // 异步for循环,数据量大的情况下可加快执行效率
                // 千万不要在次循环中往公用的集合中添加值,存在数据被覆盖的情况
                Parallel.For(0, count, t =>
                {
                    var num = t + 1;
                    //log.Info(num);
                    list.Add($"第{num}条数据");
                });
                log.Info($"输出:{list.Count()}");
            }
            catch (Exception ex)
            {
                result.AddError(this.GetException(ex));
            }
            return result;
        }

通过日志输出就能看出在数据量很大的情况下会出现数据呗覆盖的情况,因此如果在for循环中涉及到对公用变量的修改,不建议使用异步for循环 

 一千条数据情况下的日志输出
2020-03-01 15:20:35.1027 INFO 输出:1000
一万条数据情况下的日志输出
2020-03-01 15:21:08.4059 INFO 输出:6109

 Parallel.ForEach()的用法跟 Parallel.For()的用法略有不同,但是基本一致,同样也存在数据覆盖的问题。

                Parallel.ForEach(list, item =>
                {
                    Console.WriteLine(item);
                });

注意:数据量很大的情况下会出现数据呗覆盖的情况

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值