C# 跨线程操作控件


01.using System; 
02.using System.Collections.Generic; 
03.using System.ComponentModel; 
04.using System.Data; 
05.using System.Drawing; 
06.using System.Text; 
07.using System.Windows.Forms; 
08.using System.Threading; 
09.   
10.namespace JPGCompact 
11.{ 
12.    public partial class MainForm : Form 
13.    { 
14.        // 定义委托 
15.        private delegate void DelegateWriteResult(string file, bool result); 
16.   
17.        // 与定义的委托签名相同的函数,操作主线程控件 
18.        private void WriteResult(string fileName, bool result) 
19.        { 
20.            if (result)
21.            { 
22.                ListViewItem thisListItem = new ListViewItem(); 
23.                thisListItem.ForeColor = Color.White; 
24.                thisListItem.BackColor = Color.DarkGreen; 
25.                thisListItem.SubItems[0].Text = fileName; 
26.                thisListItem.SubItems.Add("成功"); 
27.                lvResultList.Items.Add(thisListItem); 
28.            } 
29.            else 
30.            { 
31.                ListViewItem thisListItem = new ListViewItem(); 
32.                thisListItem.ForeColor = Color.White; 
33.                thisListItem.BackColor = Color.Red; 
34.                thisListItem.SubItems[0].Text = fileName; 
35.                thisListItem.SubItems.Add("失败"); 
36.                lvResultList.Items.Add(thisListItem); 
37.            } 
38.        } 

39.   
40.        // 启动线程 
41.        private void btnStart_Click(object sender, EventArgs e) 
42.        { 
43.            Thread workThread = new Thread(new ThreadStart(CompressAll)); 
44.            // 设置为背景线程,主线程一旦推出,该线程也不等待而立即结束 
45.            workThread.IsBackground = true; 
46.            workThread.Start(); 
47.        } 
48.   
49.        // 线程执行函数 
50.        private void CompressAll() 
51.        { 
52.            // 判断是否需要Invoke,多线程时需要 
53.            if (this.InvokeRequired) 
54.            { 
55.                // 通过委托调用写主线程控件的程序,传递参数放在object数组中 
56.                this.Invoke(new DelegateWriteResult(WriteResult), 
57.                                new object[] { item, true }); 
58.            } 
59.            else 
60.            { 
61.                // 如果不需要委托调用,则直接调用 
62.                this.WriteResult(item, true); 
63.            } 
64.        } 
65.    } 
66.}   

 


 
 
C#跨线程操作控件               问题       
        因为我的C#程序全是在VS2005上作的,以前学VB.NET的时候机器上是有VS2003的,现在没有2003了,所以我提出的问题不知道VS2003上有没有,看了不少关于线程操作的文章,都没有找到满意的答案.            错误请看代码: 

              private void change()        

 { 

            this.label1.Text = "已发生变化";      

   } 

private void button1_Click(object sender, EventArgs e) //按钮事件      

   { 

            Thread cha = new Thread(new ThreadStart(change));            

 cha.Start();        

 } 

            错误提示: 
           未处理 System.InvalidOperationException 
Message="线程间操作无效: 从不是创建控件“label1”的线程访问它。" Source="System.Windows.Forms" StackTrace: 
       在 System.Windows.Forms.Control.get_Handle() 
       在 System.Windows.Forms.Control.set_WindowText(String value)        在 System.Windows.Forms.Control.set_Text(String value)        在 System.Windows.Forms.Label.set_Text(String value)        在 进程控件.Form1.change() 位置 C:\Documents and 
Settings\win.LEGEND-ECDE46B9\My Documents\Visual Studio 2005\Projects\进程控件\进程控件\Form1.cs:行号 15 
       在 System.Threading.ThreadHelper.ThreadStart_Context(Object state) 

       在 System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)        在 System.Threading.ThreadHelper.ThreadStart()               无法跨线程操作,与创建控件的线程不一致           


  解决方法: 

private void change()      

   { 

            this.label1.Text = "已发生变化";      

   } 

private void threadchange()   //通过委托处理,MSDN上又很详细用法的说明 
        { 


            MethodInvoker In = new MethodInvoker(change);           

  this.BeginInvoke(In);        

 } 

private void button1_Click(object sender, EventArgs e)        

 { 

            Thread cha = new Thread(new ThreadStart(threadchange));             

cha.Start();        

 } 

程序测试成功





例子2:

  初试C#,结果发现原在Java里面可以实现的子线程调用主窗体空间,在C#中会抛出异常,子线程和运行窗体的线程在不同的空间,这样的跨线程调用C#编译器视为危险调用方法,所以抛出异常。

      使用委托和Invoke方法。

     private delegate void addStatusUnSafe(string status);
      public void addStatus(string status)
      {
          DateTime dt = System.DateTime.Now;
          string now = "[" + dt.ToShortDateString() + " " + dt.ToShortTimeString() + "]";

          if (this.listBoxStatus.InvokeRequired)
          {
              addStatusUnSafe aus = new addStatusUnSafe(addStatus);
              this.listBoxStatus.Invoke(aus, new string[] { status });
          }
          else
          {
              this.listBoxStatus.Items.Add(now + status);
              if (this.listBoxStatus.Items.Count > 0)
              {
                  this.listBoxStatus.SelectedIndex = this.listBoxStatus.Items.Count - 1;
              }
          }

      }



例子3:


1、取消线程安全保护模式
  在程序初始化的时候对要操作的控件设置下面的属性:
  System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls  =  false;
  2、副线程函数中通过Control.Invoke(Delegate d)来通过委托方式来调用处理控件的方法。
  线程函数:
private void go()
{
while (b)
{
listBox1.Invoke(new DDO(cc));//DDO为委托类型 private delegate void DDO();cc为一个新函数
Thread.Sleep(2000);
}
}
private void cc()//在这个函数中执行操作主线程的控件
{
listBox1.Items.Add(System.DateTime.Now.ToString());
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值