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;