日期:2014-05-18  浏览次数:20761 次

C# 线程的运用
C/S结构,界面启动时需要加载数据,数据存在大量的运算,导致界面启运慢,想通过C#线程来解决.

在界面Load方法中,加载数据,使用如下:  

  delegate void InitSystemMenuInvoker(); //委托,加载一些填充数据
  private Thread SystemMenuThread = null; //加载线程

界面调用
  private void MainFrame_Load(object sender, EventArgs e) /
  {
  //InitSystemMenu();
  SystemMenuThread = new Thread(new ThreadStart(SystemMenuInvok));//
  SystemMenuThread.Start();  
  }
委托运行
  private void SystemMenuInvok()
  {
  ///委托运行的方法
  InitSystemMenuInvoker menu = new InitSystemMenuInvoker(InitSystemMenu);
  BeginInvoke(menu);  
  }

在运行时,总会出现,界面死在那里,等线程加载完数据才显示,有什么办法可以让界面正常显示,线程在后台加载数据,不影响用户对UI的操作.
还有,线程运行完之后,怎么关闭掉,就是如何监测到这个线程已加载完数据.

------解决方案--------------------
设置线程属性BackgroundWorker为true

线程执行完后会自动结束

如果想监听线程已完成的消息,可参考异步模式的做法:

ms-help://MS.VSCC.v90/MS.MSDNQTR.v90.chs/dv_fxadvance/html/792aa8da-918b-458e-b154-9836b97735f3.htm

部分摘录:

那些同时执行多项任务、但仍能响应用户交互的应用程序通常需要实施一种使用多线程的设计方案。System.Threading 命名空间提供了创建高性能多线程应用程序所必需的所有工具,但要想有效地使用这些工具,需要有丰富的使用多线程软件工程的经验。对于相对简单的多线程应用程序,BackgroundWorker 组件提供了一个简单的解决方案。对于更复杂的异步应用程序,请考虑实现一个符合基于事件的异步模式的类。

基于事件的异步模式具有多线程应用程序的优点,同时隐匿了多线程设计中固有的许多复杂问题。使用支持此模式的类,您将能够: 

“在后台”执行耗时任务(例如下载和数据库操作),但不会中断您的应用程序。

同时执行多个操作,每个操作完成时都会接到通知。

等待资源变得可用,但不会停止(“挂起”)您的应用程序。

使用熟悉的事件和委托模型与挂起的异步操作通信。有关使用事件处理程序和委托的更多信息,请参见 事件和委托。

支持基于事件的异步模式的类将有一个或多个名为 方法名称Async 的方法。这些方法可能会创建同步版本的镜像,这些同步版本会在当前线程上执行相同的操作。该类还可能有一个 方法名称Completed 事件,而且它可能会有一个 方法名称AsyncCancel(或只是 CancelAsync)方法。

PictureBox 是一个支持基于事件的异步模式的典型组件。您可以通过调用其 Load 方法来同步下载图像,但是如果图像很大,或者网络连接很慢,您的应用程序将停止(“挂起”),直到下载操作完成并且对 Load 的调用返回后才会继续执行。

如果您希望您的应用程序在加载图像时保持运行,您可以调用 LoadAsync 方法,处理 LoadCompleted 事件,这与您处理任何其他事件没有什么两样。调用 LoadAsync 方法时,您的应用程序将继续运行,而下载操作将在另一个线程上(“在后台”)继续。图像加载操作完成时,将会调用您的事件处理程序,您的事件处理程序可以检查 AsyncCompletedEventArgs 参数以确定下载是否已成功完成。

基于事件的异步模式要求异步操作可以取消,PictureBox 控件使用其 CancelAsync 方法来支持此要求。调用 CancelAsync 会提交一个停止挂起的下载的请求,任务取消时会引发 LoadCompleted 事件。


------解决方案--------------------
C# code
1 private SortedList sl = null;
 2  private const int  TEST_COUNT = 10000;
 3  private void button1_Click(object sender, System.EventArgs e)
 4  {
 5   mi = new MethodInvoker(DoWork);
 6   mi.BeginInvoke(new AsyncCallback(DoneWork), null);
 7  }
 8  private void DoWork()
 9  {
10   sl = new SortedList();
11   InitialPB(TEST_COUNT);
12   for (int i =0;i<TEST_COUNT;i++)
13   {
14    sl.Add(i,"NoWay" + i.ToString());
15    Thread.Sleep(100);
16    RefreshText("NoWay" + i.ToString());
17    RefreshPB(1);
18   }
19   
20  }
21  private void InitialPB(int max)
22  {
23   if( InvokeRequired )
24   {
25    this.Invoke( new IntDelegate(InitialPB), new object [] { max } );
26    return ;
27   }
28   progressBar1.Maximum = max ;
29   progressBar1.Value = 0;
30  }
31  private void RefreshText(string item)
32  {
33   if( InvokeRequired )
34   {
35    this.Invoke( new StringDelegate(RefreshText), new object [] { item } );
36    return ;
37   }
38   this.textBox1.Text = item;
39  }
40  private void RefreshPB(int Value)
41  {
42   if( InvokeRequired )
43   {
44    this.Invoke( new IntDelegate(RefreshPB), new object [] {Value} );
45    return ;
46   }
47   progressBar1.Value+=Value;
48  }
49  private void DoneWork(IAsyncResult result)
50  {
51   if( InvokeRequired )
52   {
53    Invoke(new AsyncCallback(DoneWork), new Object [] { result } );
54    return ;
55   }
56   MessageBox.Show("Done!")
57;
58  }
59  private void button2_Click(object sender, System.EventArgs e)