多线程开发

      前不久写了一个项目,其中需要处理大量的数据,这些数据都是记录型的,对这些数据进行处理是一个非常耗时的事情,.net在处理这些使用的过程中,就好像死机一样一动不动。这样给用户的感觉非常的不好。例如如下的例子,我们在一个窗体上放置一个ProgressBar,然后对ProgressBar进行循环添加,例如:

 1         private void btnProcess_Click(object sender, EventArgs e)
 2         {
 3             int nStart = Convert.ToInt32(txtStart.Text);
 4             int nEnd = Convert.ToInt32(txtEnd.Text);
 5 
 6             prgProcess.Minimum = nStart;
 7             prgProcess.Maximum = nEnd;
 8             for (int nValue = nStart; nValue <= nEnd; nValue++)
 9             {
10                 lblStatus.Text = "Processing item: " + Convert.ToString(nValue);
11                 prgProcess.Value = nValue;
12             } } 

      这段代码运行时正常的,但是对于数据量很大的时候,比如txtEnd.Text设置成1000000,这个时候界面上的进度条也许就是个固定值,一动不动,而且lblStatus.Text的现实也是为空,这是很正常的。程序就如同死机一样。当然,我们可以在循环中添加Application.DoEvents();使系统在空闲的时间处理其他的事情,这样系统的效果会好些。例如:

 1 private void btnProcess_Click(object sender, EventArgs e)
 2         {
 3             int nStart = Convert.ToInt32(txtStart.Text);
 4             int nEnd = Convert.ToInt32(txtEnd.Text);
 5 
 6             prgProcess.Minimum = nStart;
 7             prgProcess.Maximum = nEnd;
 8             for (int nValue = nStart; nValue <= nEnd; nValue++)
 9             {
10                 lblStatus.Text = "Processing item: " + Convert.ToString(nValue);
11                 prgProcess.Value = nValue;
12 
13                 Application.DoEvents();
14             }
15         }

      但这些不是本文的重点,本文的重点是使用多线程的的方式去处理这些内容,我们将在此窗体中添加Tread去处理这些复杂的操作。这样的效果会比Application.DoEvents();更好。

      还是在原来的窗体上,我们使用线程的方式去处理。

 1         delegate void DelegateType(int x);
 2         DelegateType TheDelegate;
 3 
 4         int StartFrom, EndTo;
 5 
 6         private void btnStartThreaded_Click(object sender, EventArgs e)
 7         {
 8             TheDelegate = MessageHandler;
 9 
10             StartFrom = Convert.ToInt32(txtStart.Text);
11             EndTo = Convert.ToInt32(txtEnd.Text);
12 
13             prgProcess.Minimum = StartFrom;
14             prgProcess.Maximum = EndTo;
15 
16             btnStartThreaded.Enabled = false;
17 
18             Thread MyThread = new Thread(ProcessRoutine);
19             MyThread.Start();
20         }
21 
22         void MessageHandler(int nProgress)
23         {
24             lblStatus.Text = "Processing item: " + Convert.ToString(nProgress);
25             prgProcess.Value = nProgress;
26         }
27 
28         void ProcessRoutine()
29         { 
30             for (int nValue = StartFrom; nValue <= EndTo; nValue++)
31             {
32                 this.Invoke(this.TheDelegate, nValue);
33             }

34         }

       这个是使用线程的方法去处理,但是问题还是有的,虽然线程处理了用户界面效果的问题,但是对于大数据量处理过程中,很耗时的,用户可能会去取消自己的操作,所以我们要添加方法去对自己的线程取消。微软这个方面做的很好,它提供了ManualResetEvent的委托类,可以轻松的对线程进行取消。代码如下:

       首先添加ManualResetEvent的委托:

   ManualResetEvent CancelEvent = new ManualResetEvent(false); 

        private void btnCancelButton_Click(object sender, EventArgs e)
        {
            btnCancelButton.Enabled 
= false;

            CancelEvent.Set();
            MyThread.Join();

            lblStatus.Text 
= "Cancelled!";

        } 

        修改ProcessRoutine的代码如下:

   void ProcessRoutine()
        {
            
for (int nValue = StartFrom; nValue <= EndTo; nValue++)
            {

                if (CancelEvent.WaitOne(0false== true)
                {
                    
return;
                }
                
this.BeginInvoke(this.TheDelegate, nValue);
                Thread.Sleep(
200);
            }
        }

       另外一点,我们还可以对线程进行扩充,就是将线程的暂停和继续,这个就很简单了,就是对线程的Suspend和Resume,只要再添加按钮设置线程的Suspend和Resume就可以了。代码如下:

        bool IsThreadPaused;
        private void btnPause_Click(object sender, EventArgs e)
        {
            
if (!IsThreadPaused)
            {
                IsThreadPaused 
= true;
                MyThread.Suspend();
                btnPause.Text 
= "Resume";
                lblStatus.Text 
= "Paused!";
                btnCancelButton.Enabled 
= false;
            }
            
else
            {
                IsThreadPaused 
= false;
                MyThread.Resume();
                btnPause.Text 
= "Pause";
                btnCancelButton.Enabled 
= true;
            }
        }

  

 

posted @ 2009-11-19 12:49 萧萧空间 阅读(...) 评论(...) 编辑 收藏