예제 #1
0
        public static void Initlize(params string[] bussinessTypes)
        {
            BackGroundMessageMgr messageMgr = new BackGroundMessageMgr(bussinessTypes);

            messageMgr.OnBackGroundMessageReceive += MessageMgr_OnBackGroundMessageReceive;
        }
예제 #2
0
        /// <summary>
        /// 处理导入导出消息
        /// </summary>
        /// <param name="m">消息</param>
        /// <param name="ex">异常</param>
        /// <returns>处理结果,决定是否删除消息</returns>
        private static bool MessageMgr_OnBackGroundMessageReceive(Protocol.MQProtocol.MQProtocol <SetBackGroudMessageArgs> m, System.Exception ex)
        {
            try
            {
                BmmHelp bmm = new BmmHelp(m?.Msg?.Args?.rid);
                bmm.SetStartProgress();
                logger.LogDebug($"开始处理消息[{m?.Msg?.Args?.rid}]: {m?.ToString()}");
                var code = new StatusCode(805, "导入导出消息分发时发生异常");
                if (ex != null || m?.Msg?.Args == null)
                {
                    bmm.SetFailProgress(code, int.MaxValue);
                    logger.LogError($"处理消息[{m?.Msg?.Args?.rid}] 异常 : 导入导出消息分发时发生异常");
                    //return true;
                }

                if (m?.Msg != null)
                {
                    SetBackGroudMessageArgs args = m.Msg;
                    try
                    {
                        var ctxArgs = args.Args.Copy();
                        ctxArgs.ct = "Import & Export function inner use.";
                        var data = JsonConvert.DeserializeObject <object>(args.Data, new JsonSerializerSettings()
                        {
                            DefaultValueHandling = DefaultValueHandling.Populate
                        });
                        ctxArgs.v = data;
                        MicroServiceAssembly.Run(args.BussinessType, ctxArgs, out code);

                        if (code.code != StatusCode.OK.code)
                        {
                            bmm.SetFailProgress(code, int.MaxValue);
                            logger.LogError($"消息[{m.Msg.Args?.rid}] Initialization.MessageMgr_OnBackGroundMessageReceive.Error.args={m.ToString()},code:{code.code},msg:{code.msg}");
                            //return false;
                        }

                        // 消息兜底异步处理
                        var rst = BackGroundMessageMgr.GetProcessStatus(m.Msg.Args?.rid);
                        if (rst == null || (rst.Code.IsSuccess && (rst.ProcessNum != rst.TotalNum || rst.ProcessNum == -1)))
                        {
                            bmm.SetSuccessProgress(
                                (rst?.TotalNum ?? -1) == -1 ? int.MaxValue : rst?.TotalNum ?? int.MaxValue,
                                rst?.SuccessNum ?? 0,
                                "框架兜底完成异步任务");
                            logger.LogWarning($"消息[{m.Msg.Args?.rid}] 处理返回成功,但是没有设置进度100%,{m.ToString()},code:{code.code},msg:{code.msg}");
                            //return true;
                        }
                    }
                    catch (Exception e)
                    {
                        StatusCode c = new StatusCode(500, "ImportExportMsgDeal.MessageMgr_OnBackGroundMessageReceive.Error=" + e.Message);
                        bmm.SetFailProgress(c, int.MaxValue);
                        logger.LogError(e, $"消息[{m.Msg.Args?.rid}] Initialization.MessageMgr_OnBackGroundMessageReceive.Error.args={m.ToString()}");
                        //return false;
                    }

                    logger.LogDebug($"结束处理消息[{m.Msg.Args?.rid}] .");
                }
            }
            catch (Exception ex1)
            {
                logger.LogError(ex1, $"处理消息[{m?.Msg?.Args?.rid}] .异常...");
            }
            return(true);
            //这里最大的问题是如果MQ在连续3个消息都没有收到ACK就不在给这个客户端发送消息,直到收到为止
            // 全部返回ACK  因为消息到这里来,就说明已经收到消息了,最终错误会写到Redis里面,前端还是接到了错误响应,本条消息处理完毕,而不是把完毕的消息继续留在队列中  add by grant 2019-2-26
        }
예제 #3
0
파일: TaskEx.cs 프로젝트: staoran/SuperGMS
        /// <summary>
        /// 并行执行操作
        /// </summary>
        /// <param name="tables">要多线程批量执行的集合</param>
        /// <param name="runOne">集合中每一项要执行的操作</param>
        /// <param name="callBack">最后集合执行完的回调</param>
        /// <param name="ctx">RpcContext</param>
        /// <param name="userCtx">userCtx</param>
        /// <param name="taskNum">同时并发的线程数 默认为10,用户可以自己指定这个值</param>
        /// <param name="userTotNum">默认为tables.length来算,用户可以自己指定这个值</param>
        /// <returns>返回执行结果</returns>
        public static List<TaskExResult<T>> DoRun(T[] tables, Func<TaskExArgs<T>, TaskExResult<T>> runOne, Func<List<TaskExResult<T>>, TaskExCallBackResult> callBack, RpcContext ctx, object userCtx, int taskNum = 0, int userTotNum = 0)
        {
            if (tables == null || runOne == null)
            {
                return null;
            }
            if (taskNum > 20)
            {
                taskNum = 20;
            }

            List<Task> li = new List<Task>();
            List<TaskExResult<T>> rst = new List<TaskExResult<T>>();
            object lockObj = new object();
            int current = 0;
            int success = 0;
            for (int i = 0; i < tables.Length; i++)
            {
                var item = new TaskExArgs<T>() { Row = tables[i], UserCtx = userCtx, RowIndx = i, Tables = tables,TaskResult = rst};
                Task tsk = new Task(() =>
                {
                    bool isOk = false;
                    TaskExResult<T> r;
                    try
                    {
                        // 这里try一下,防止外面传进来的方法没有处理异常,
                        // 但是强烈建议,外部自己处理异常,这样可以根据业务决定返回true,false,外部处理了异常,这里就不会捕获到
                        r = runOne(item);
                        isOk = r.IsSuccess;
                    }
                    catch (Exception ex)
                    {
                        r = new TaskExResult<T>
                        {
                            IsSuccess = false,
                            Ex = ex,
                        };
                        isOk = false;
                    }
                    r.Row = item.Row;
                    r.Tables = tables;
                    r.RowIndx = item.RowIndx;
                    r.Row = item.Row;
                    lock (lockObj)
                    {
                        rst.Add(r); // 把每行的执行情况保存下来,在最后执行完毕后返回给调用方

                        int cur_tot = r.TotNum > 0 ? r.TotNum : 1;
                        int tot_org = userTotNum > 0 ? userTotNum : tables.Length;

                        if (isOk)
                        {
                            int succ = r.SuccessNum > 0 ? r.SuccessNum : 1;
                            success += succ;
                        }
                        else
                        {
                            int succ = r.SuccessNum > 0 ? r.SuccessNum : 0;
                            success += succ;
                        }

                        current += cur_tot;
                        TaskExCallBackResult callRst = null;
                        if (current >= tot_org)
                        {
                            try
                            {
                               callRst = callBack(rst); // 完成之后执行回调
                            }
                            catch (Exception e)
                            {
                                logger.LogError(e, $"TaskEx.DoRun.callBack.Error.rid={ctx.Args.rid}");

                                // 把错误返回给客户端
                                callRst = new TaskExCallBackResult()
                                {
                                    SetCallBackData =
                                        $"TaskEx.DoRun.callBack.Error.rid={ctx.Args.rid},ex={e.Message},exState={e.StackTrace}",
                                };
                            }
                        }
                        BackGroundMessageProcessResult backGround = new BackGroundMessageProcessResult()
                        {
                            Code = StatusCode.OK,
                            Rid = ctx.Args.rid,
                            TotalNum = tot_org,
                            Data = callRst == null ? null : Newtonsoft.Json.JsonConvert.SerializeObject(callRst.SetCallBackData),
                        };

                        if (!string.IsNullOrEmpty(r.Data))
                        {
                            if (callRst == null) // 最后的内容以以回调为准
                            {
                                backGround.Data = r.Data;
                                r.Data = String.Empty;
                            }
                        }

                        backGround.SuccessNum = success;
                        backGround.ProcessNum = current;

                        BackGroundMessageMgr.SetProcessStatus(backGround);
                    }
                });
                tsk.Start();
                li.Add(tsk);
                if (li.Count >= (taskNum > 0 ? taskNum : 10) || (i == (tables.Length - 1)))
                {
                    Task.WaitAll(li.ToArray());
                    li.Clear();
                }

                 if(taskNum > 1) Thread.Sleep(1);
            }

            return rst;
        }