在C#中,经常会有一些耗时较长的CPU密集型运算,因为如果直接在UI线程执行这样的运算就会出现UI不响应的问题。解决这类问题的主要途径是使用多线程,启动一个后台线程,把运算操作放在这个后台线程中完成。但是原生接口的线程操作有一些难度,如果要更进一步的去完成线程间的通讯就会难上加难。
因此,.NET类库中提供了一个叫做BackgroundWorker的类可以比较优雅的解决这类问题。虽然BackgroundWorker类使用起来比较简单,但其中还是有一些需要注意的细节,下面我们就通过一个简单的Dmeo程序,来详细介绍它的主要用法。我们在Demo中计算1到100的累加和,为了演示效果,每次计算都睡眠600毫秒,Demo的界面如下:
用法概述:
在窗体上构建一个BackgroundWorker实例,在它的DoWork事件处理函数中添加耗时的运算,然后调用它的RunWorkerAsync方法就可以了。
private BackgroundWorker _demoBGWorker=new BackgroundWorker();
public Form1()
{
InitializeComponent();
}
private void BGWorker_DoWork(object sender, DoWorkEventArgs e)
{
//在这里执行耗时运算。
int sum = 0;
for(int i = 0; i < 100; i++)
{
sum += i;
}
}
private void btnStart_Click(object sender, EventArgs e)
{
_demoBGWorker.DoWork += BGWorker_DoWork;
_demoBGWorker.RunWorkerAsync();
}
以上部分,暂时没有加入进度条的显示逻辑,以及其余耗时的计算,但我们可以先考虑下面几个问题:
如果我们要想把参数传递给运算过程怎么做?
在运算过程中我们希望把实时的信息显示在UI上应该怎么办?
如果我们想要取消正在进行的运算该怎么办?
如果运算过程出现异常我们又该如何处理?
接下来我们就一个一个的处理这些问题。
一、把参数传递给运算过程:
直接把100写死到运算过程中一般是不会用到的,常见的方式,都是客户指定求和的范围。因此我们在通过调用RunWorkerAsync方法启动计算过程时,这个方法可以接受一个object类型的参数,我们可以通过它把任何数据传递给计算过程:
private void BGWorker_DoWork(object sender, DoWorkEventArgs e)
{
//在这里执行耗时运算。
int endNumber = 0;
if (e.Argument