这篇文章主要介绍了Winform 实现进度条弹窗和任务控制的方法,帮助大家更好的利用c# winform进行开发,感兴趣的朋友可以了解下
最近要给一个 Winform 项目添加功能,需要一个能显示进度条的弹窗,还要求能够中止任务,所以就做了一个,在此做个记录总结。虽然用的是比较老的 Winform 技术,不过其中的原理都是相通的。
一、弹窗前台
首先提供一个 Winform 控件居中的小技巧:
将控件放在 TableLayoutPanel 容器中,然后将控件的 Anchor 属性设置为 None,这样控件就能在容器中居中了:
/// <summary>
/// 执行操作事件
/// </summary>
public event Action OperateAction;
/// <summary>
/// 终止操作事件
/// </summary>
public event Action AbortAction;
/// <summary>
/// 中止按钮点击事件
/// </summary>
private void btn_Abort_Click(object sender, EventArgs e)
{
AbortAction?.Invoke();
DialogResult = DialogResult.Abort;
//Close(); //不需要手动关闭;
}
/// <summary>
/// 窗体载入事件
/// </summary>
private void FormProgressDialog_Load(object sender, EventArgs e)
{
Task.Factory.StartNew(() =>
{
OperateAction?.Invoke();
DialogResult = DialogResult.OK;
});
}
点击中止按钮后还将弹窗结果设为 Abort,会自动关闭弹窗;而业务操作正常执行完毕,弹窗结果为 OK。
供外界设置文本信息以及进度条进度的方法如下:
/// <summary>
/// 设置显示信息(值为null时保持不变)
/// </summary>
/// <param name="rtfTitleContent">富文本格式的标题内容</param>
/// <param name="totalMessage">总体消息</param>
/// <param name="currentMessage">当前消息</param>
public void SetInfo(string rtfTitleContent = null, string totalMessage = null, string currentMessage = null)
{
if (rtfTitleContent != null) rtb_Title.Rtf = rtfTitleContent;
if (totalMessage != null) lbl_Total.Text = totalMessage;
if (currentMessage != null) lbl_Current.Text = currentMessage;
}
/// <summary>
/// 设置进度
/// </summary>
/// <param name="currentValue">当前数值</param>
/// <param name="totalValue">总数值</param>
public void SetProsess(double currentValue, double totalValue)
{
try
{
progressBar.Value = (int)(currentValue / totalValue * 100);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
剩下就是两个设置富文本框 RichTextBox 的方法,包括设置彩色内容和隐藏 RichTextBox 光标的方法,文末会给出代码地址,此处不再赘述。
三、使用方法
首先映入眼帘的是两个成员变量,一个是用于任务取消的 CancellationTokenSource 对象,另一个是用于线程同步的 AutoResetEvent 对象(用于取消任务后的一些信息同步);然后是主测试方法(一个按钮点击事件方法)中的一些信息设置:
#region 测试任务进度条弹窗
private CancellationTokenSource _Cts; //任务取消令牌;
private AutoResetEvent _AutoResetEvent = new AutoResetEvent(false);//参数传 false,则 WaitOne 时阻塞等待;
/// <summary>
/// 测试任务进度弹窗
/// </summary>
private void BtnProgressDialog_Click(object sender, EventArgs e)
{
_AutoResetEvent.Reset();
string businessName = "业务1";
FormProgressDialog progressWindow = new FormProgressDialog()
{
Text = "任务处理窗口",
};
progressWindow.SetColorfulTitle("业务1 ", Color.DarkOrange, true);
progressWindow.SetColorfulTitle("正在执行中......", Color.Black);
progressWindow.SetInfo(null, "", "");
List<string> orders = new List<string>(){"订单1", "订单2", "订单3", "订单4", "订单5" }; //业务数据;
List<string> leftList = orders.Select(x => x).ToList(); //剩余(未处理)数据;
int successCount = 0; //成功数量;
_Cts = new CancellationTokenSource();
//注册一个将在取消此 CancellationToken 时调用的委托;
_Cts.Token.Register(async () =>
{
ShowInfo("操作终止");
await Task.Run(() =>
{
_AutoResetEvent.WaitOne(1000 * 5); //等待有可能还在执行的业务方法;
if (successCount < orders.Count)
{
ShowInfo($"{businessName} 有 {orders.Count - successCount} 项任务被终止,可在消息框中查看具体项。");
foreach (var leftName in leftList)
{
ShowInfo($"【{businessName}】的【{leftName}】执行失败,失败原因:【手动终止】。");
}
}
});
});
progressWindow.OperateAction += () =>
{
Task task = new Task(() =>
{
foreach (var order in orders)
{
//判断是否被取消;
if (_Cts.Token.IsCancellationRequested)
{
break;
}
progressWindow.TryBeginInvoke(new Action(() =>
{
progressWindow.SetInfo(null, $"共{orders.Count}项,已执行{successCount}项", $"当前正在执行:{order}");
}));
if (BusinessMethod(order, businessName))
{
successCount++;
leftList.RemoveAll(x => x == order);
if (_Cts.Token.IsCancellationRequested)
{
_AutoResetEvent.Set(); //放行 Register 委托处的等待;
}
}
progressWindow.TryBeginInvoke(new Action(() =>
{
progressWindow.SetProsess(orders.IndexOf(order) + 1, orders.Count);
}));
}
}, _Cts.Token);
task.Start();
task.Wait();
};
progressWindow.AbortAction += () =>
{
_Cts.Cancel();
};
var result = progressWindow.ShowDialog();
int leftCount = orders.Count - successCount;
if (result == DialogResult.OK || leftCount <= 0)
{
ShowInfo($"{businessName} 整体完成。");
}
else if (result == DialogResult.Abort)
{
//移到 _Cts.Token.Register 处一起判断,不然数目可能不准;
//ShowInfo($"{businessName} 有 {leftCount} 项任务被终止,可在消息框中查看具体项。");
}
}
/// <summary>
/// 业务处理方法
/// </summary>
private bool BusinessMethod(string order, string businessName)
{
string errStr = $"【{businessName}】的 {order} 任务失败,失败原因:";
//测试
Thread.Sleep(1000 * 2);
try
{
//业务方法;
ShowInfo($"【{businessName}】的 {order} 任务执行成功。");
return true;
}
catch (Exception ex)
{
ShowInfo($"{errStr}{ex.Message}");
}
return false;
}
#endregion
四、效果展示和代码地址
正常执行(动图):
代码地址:https://gitee.com/dlgcy/Practice/tree/master/WinFormPractice
转载自 独立观察员•博客
以上就是Winform 实现进度条弹窗和任务控制的详细内容,更多关于Winform 进度条弹窗和任务控制的资料请关注得得之家其它相关文章!
本文标题为:Winform 实现进度条弹窗和任务控制
- 在C# 8中如何使用默认接口方法详解 2023-03-29
- .NET CORE DI 依赖注入 2023-09-27
- Unity Shader实现模糊效果 2023-04-27
- c# 模拟线性回归的示例 2023-03-14
- WPF使用DrawingContext实现绘制刻度条 2023-07-04
- 如何使用C# 捕获进程输出 2023-03-10
- Unity3D实现渐变颜色效果 2023-01-16
- user32.dll 函数说明小结 2022-12-26
- Oracle中for循环的使用方法 2023-07-04
- C# 使用Aspose.Cells 导出Excel的步骤及问题记录 2023-05-16