遗忘海岸

江湖程序员 -Feiph(LM战士)

导航

BackgroundWorker使用备忘

UI类似下面,带进度条与提示信息

 任务类代码

View Code
    /// <summary>
    /// 利润分析类
    /// </summary>
    public class ProfitAnalys
    {
        public ProfitAnalys(BackgroundWorker worker, DateTime bTime, DateTime eTime)
        {
            this.Worker = worker;
            this.BTime = bTime;
            this.ETime = eTime;
        }

        /// <summary>
        /// 材料每吨锻造费用
        /// </summary>
        public decimal? DealFeePerT { get; set; }
        /// <summary>
        /// 钢料每吨价格
        /// </summary>
        public decimal? MPricePerT { get; set; }

        public DateTime BTime { get; set; }
        public DateTime ETime { get; set; }
        private BackgroundWorker Worker { get; set; }
        private void Report(int progress, ReportInfo data)
        {
            if (Worker == null) return;
            Worker.ReportProgress(progress, data);
        }
        public BaseProfit Do()
        {
                string bTimeStr = BTime.ToString("yyyy-MM-dd");
                string eTimeStr = ETime.Date.ToString("yyyy-MM-dd HH:mm:ss");
                var cmdText="";
                var sql="";

               
                //获取材料价格(元/吨)
                var mPrice = MPricePerT;
                if (!(mPrice > 0)) throw new Exception("未提供钢材价格!");

                #region 为协库材料价值计算
                //获取外协库存
                Report(10, new ReportInfo() { Msg = "获取外协材料库存!" });
                cmdText = CtxFactory.GetSql(69);
                sql = cmdText.Replace("$BDate", bTimeStr).Replace("$EDate", eTimeStr);
                var mOutInventory = ExecSql<MInventory>(sql);
                //外协库材料价值
                Report(30, new ReportInfo() { Msg = "计算外协库材料价值" });
                var MInventoryWorth = 0.0m;
                if (mOutInventory.Count > 0)
                {
                    MInventoryWorth = mOutInventory[0].BalanceQty.Value * mPrice.Value;
                }
                #endregion

                #region 在制品材料价值计算
                //获取在制产品数量列表
                Report(50, new ReportInfo() { Msg = "获取在制产品数量列表" });
                cmdText = CtxFactory.GetSql(68);
                sql = cmdText.Replace("$BDate", bTimeStr).Replace("$EDate", eTimeStr).Replace("$Condition", "");
                var pList = ExecSql<PInventory>(sql).Where(ent => ent.BalanceQty > 0).ToList();
                //获在制品重量
                Report(60, new ReportInfo() { Msg = "获取在产品档案数据" });
                sql = "select RTrim(p_Partno) MNo,RTrim(p_partName) MName ,p_Weight_mp Weight from p_partno_rm";
                var pWeightList = ExecSql<PWeight>(sql);
                //换算在制产品材料重量
                Report(70, new ReportInfo() { Msg = "获取在产品档案数据" });
                var tmpList = pList.Join(pWeightList, p => p.MNo.Trim(), w => w.MNo.Trim(), (p, w) => new { Weight = w.Weight, MNo = p.MNo, MName = p.MName, Qty = p.BalanceQty }).ToList();
                //确保设置了产品单重检测
                tmpList.ForEach(ent =>
                {
                    if (!(ent.Weight > 0))
                    {
                        throw new Exception(string.Format("物料:{0}没在[产品档案]中设定有效的重量参数!", ent.MNo.Trim()));
                    }
                });
            
                //计算在制产品材料价值
                var pTotalWeight = (tmpList.Select(ent => ent.Qty * ent.Weight).Sum()) / 1000;//成品材料总重量(单位:吨)
                if(!(DealFeePerT >0))throw new Exception("未提供材料锻造费用!");

                var pWorth= pTotalWeight * mPrice.Value + pTotalWeight * DealFeePerT.Value ;
                #endregion
            
                 //费用,销售,材料成本,锻造等费用
                Report(90, new ReportInfo() { Msg = "计算销售、材料、运费、费用等汇总金额..." });

                cmdText = CtxFactory.GetSql(70);
                sql = cmdText.Replace("$BDate", bTimeStr).Replace("$EDate", eTimeStr);
                var profitList = ExecSql<BaseProfit>(sql);
                var profit=profitList[0];
                profit.MInventoryMoney=MInventoryWorth;
                profit.WIPMoney=pWorth;
                return profit;
        }
        /// <summary>
        /// 获取材料单吨价格
        /// </summary>
        /// <param name="bTime"></param>``
        /// <param name="eTime"></param>
        /// <returns></returns>
        public decimal GetPrice(DateTime eTime)
        {
            string cmdText = "select Top 1 unitPrice from dbo.SERP_RMInticket where ptype='材料' Order By ABS(datediff(hh,DealTime,'{0}')) ASC";
            var sql = string.Format(cmdText, eTime.Date.ToString("yyyy-MM-dd HH:mm:ss"));
            var list = ExecSql<decimal>(sql);
            if (list.Count <= 0 )
            {
                throw new Exception("无法获取有效的材料价格信息!");
            }
            return list[0];
        }
        private List<T> ExecSql<T>(string sql)
        {
            using (DB ctx = CtxFactory.New())
            {
                ctx.CommandTimeout = 9999;
                return ctx.ExecuteStoreQuery<T>(sql).ToList();
            }

        }


    }
    #region 结构类
    public class ReportInfo
    {
        public string Msg { get; set; }
        public int MsgType { get; set; }
        public object Data { get; set; }
    }
    public class BaseProfit
    {
        #region 收入类
        /// <summary>
        /// 铁削销售收入
        /// </summary>
        public decimal? SWInMoney { get; set; }
        /// <summary>
        /// 销售收入
        /// </summary>
        public decimal? InMoney { get; set; }

        /// <summary>
        /// 材料库存价值
        /// </summary>
        public decimal? MInventoryMoney { get; set; }
        /// <summary>
        /// 在制品价值
        /// </summary>
        public decimal? WIPMoney { get; set; }
        #endregion
        #region 成本类
        /// <summary>
        /// 材料成本
        /// </summary>
        public decimal? Cost { get; set; }
        /// <summary>
        /// 费用
        /// </summary>
        public decimal? Fee { get; set; }
        /// <summary>
        /// 工资
        /// </summary>
        public decimal? Salary { get; set; }
        /// <summary>
        /// 主运费
        /// </summary>
        public decimal? TranCost { get; set; }
        /// <summary>
        /// 锻造费用
        /// </summary>
        public decimal? DealCost { get; set; }
        #endregion

        public decimal? ProfitMoney
        {
            get
            {
                return V(SWInMoney) + V(InMoney) + V(MInventoryMoney) + V(WIPMoney)
                       - V(Cost) - V(Fee) - V(Salary) - V(TranCost) - V(DealCost);
            }
        }
        private decimal V(decimal? v)
        {
            return v.HasValue ? v.Value : 0;
        }

    }
    public class MInventory
    {
        public string MNo { get; set; }
        public string MName { get; set; }
        public decimal? BefQty { get; set; }
        public decimal? InQty { get; set; }
        public decimal? OutQty { get; set; }
        public decimal? BalanceQty { get; set; }
    }
    public class PInventory
    {
        public string MNo { get; set; }
        public string MName { get; set; }
        public decimal? BalanceQty { get; set; }

    }
    public class PWeight
    {
        public string MNo { get; set; }
        public string MName { get; set; }
        public decimal? Weight { get; set; }
    }

#endregion

 

UI代码
View Code
    using Report;
    using Microsoft.Reporting.WinForms;
    using EFModel;

    public partial class frmProfitAnalys : Form
    {
        private BackgroundWorker Worker { get; set; }
        public frmProfitAnalys()
        {
            InitializeComponent();
        }
  
        private void btnAnalys_Click(object sender, EventArgs e)
        {

            try
            {
              
                btnAnalys.Enabled = false;
                progressBar.Value = 0;
                lblTip.Text = "任务启动";
                baseProfitBindingSource.DataSource = new BaseProfit();
                this.Refresh();
                

                Worker = new BackgroundWorker();
                Worker.WorkerReportsProgress = true;
                Worker.WorkerSupportsCancellation = true;

                var bTime = dtpBTime.Value.Date;
                var eTime = dtpETime.Value.Date.AddHours(23.9999);
                var analyst = new ProfitAnalys(Worker, bTime, eTime);
                if (!ckbIsCustomer.Checked)
                {
                    this.Refresh();
                    var mPrice_ = 0.0m;
                    mPrice_ = analyst.GetPrice(eTime);
                    txtMPrice.Text = mPrice_.ToString("0.00");
                }

                decimal mPrice = 0.0m;
                decimal.TryParse(txtMPrice.Text, out mPrice);
                if (!(mPrice > 0)) throw new Exception("请提供有效的材料价格!");
                analyst.MPricePerT = mPrice;//设置价格

                decimal dealFee = 0.0m;
                decimal.TryParse(txtDealFee.Text, out dealFee);
                if (!(dealFee > 0)) throw new Exception("请提供有效的锻造费!");
                analyst.DealFeePerT = dealFee;//设置锻造费用

                #region 异步执行配置
                Worker.DoWork += (s, e1) =>
                {

                   //如果要RunWorkerCompleted中的e1.Cancelled为true
                   //那么必需在这里设置e1.Cancel=true,只调用Worker.CancelAsync不会使上面的e1.Cancell为true
                   //调用Worker.CancelAsync();会设置Worker.CancellationPending=true;
                   //可以在Do中判断CancellationPending以决定是否取消处理
                   //如果用户提交了取消则Do返回一个取消的标识对象,在这里做下判断,后设置e1.Cancel=true;
                    e1.Result = analyst.Do();

                    
                };
                //进度报告
                Worker.ProgressChanged += (s, e1) =>
                {
                    var rpt = e1.UserState as ReportInfo;
                    if (rpt != null)
                    {
                        progressBar.Value = e1.ProgressPercentage;
                        lblTip.Text = rpt.Msg;
                       
                    }
                };
                Worker.RunWorkerCompleted += (s, e1) =>
                {
                    if (e1.Cancelled)
                    {
                        lblTip.Text = "任务被取消!";
                      
                    }
                    else if (e1.Error != null)
                    {
                        lblTip.Text = "错误:" + e1.Error.Message;
                       
                    }
                    else if (e1.Result != null)
                    {
                        baseProfitBindingSource.DataSource = e1.Result;
                        baseProfitBindingSource.ResetBindings(false);
                        progressBar.Value = 100;
                        lblTip.Text = "任务完成!";
                    }

                    btnAnalys.Enabled = true;

                };
                Worker.RunWorkerAsync();
                Thread.Sleep(10);
                Worker.CancelAsync();
                #endregion
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                btnAnalys.Enabled = true;
            }


        }

        private void frmProfitAnalys_Load(object sender, EventArgs e)
        {
            txtMPrice.Enabled = false;
            ckbIsCustomer.Checked = false;
            ckbIsCustomer.Click += (s, e1) =>
            {
                if (!ckbIsCustomer.Checked)
                {
                    txtMPrice.Text = string.Empty;

                }
                txtMPrice.Enabled = ckbIsCustomer.Checked;
            };

            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
            this.MinimizeBox = false;
            this.MaximizeBox = false;

        }
    }

关于取消任务的说明
如果要RunWorkerCompleted中的e1.Cancelled为true
那么必需在这里设置e1.Cancel=true,只调用Worker.CancelAsync不会使上面的e1.Cancell为true
调用Worker.CancelAsync();会设置Worker.CancellationPending=true;
可以在Do中判断CancellationPending以决定是否取消处理
如果用户提交了取消则Do返回一个取消的标识对象,在这里做下判断,后设置e1.Cancel=true;

posted on 2012-09-30 08:25  遗忘海岸  阅读(441)  评论(0编辑  收藏  举报