有一个窗体为Form1,其上有一个Label(label1)控件及Botton(button1)控件.同时有一个类为Event,其中有一个事件为TimeUp.
现有一个问题是:我在Form1订阅了TimeUp事件,想在其上更改label1.text内容.代码如下:
窗体代码为:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;namespace EvenExcise
{
    public partial class Form1 : Form
    {
        int Times = 0;
        public Form1()
        {
            InitializeComponent();
            this.label1.Text="";
        }        private void button1_Click(object sender, EventArgs e)
        {
            Event myEvent = new Event();
            myEvent.TimeUp += new Event.EventHappenHandle(myEvent_TimeUp);
        }        void myEvent_TimeUp(object sender, EventArgs e)
        {
            Times++;
           this.label1.Text  = "这是第" + (Times + 1).ToString() + "时间到";
        }
    }
}Event类的代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;namespace EvenExcise
{
    class Event
    {
       System.Timers.Timer myTimer = new System.Timers.Timer(1000);
       public delegate void EventHappenHandle(object sender, EventArgs e);
       public event EventHappenHandle TimeUp;
      public  Event()
      {
          myTimer.Start();
          myTimer.Elapsed += new System.Timers.ElapsedEventHandler(myTimer_Elapsed);
      }            void myTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
      {
          EventArgs ee = new EventArgs();
          TimeUp(sender, ee);
      }    }
}可为什么一运行到this.label1.Text  = "这是第" + (Times + 1).ToString() + "时间到";
出错,提示如下:"线程间操作无效: 从不是创建控件“label1”的线程访问它。"
难道这种情况只能采用.invoke, 用代理方法处理,如是这样,如我要对窗体中的许多控件外观进行处理,不是要定义许多代理?
请高手指导,谢谢!

解决方案 »

  1.   

    跨线程访问的问题,看看这个例子:
    form2中定义了
    public delegate void UpdateNotice(string NoticeText);//更新notice的委托用
    public UpdateNotice AppNoticeByThread;
    前台的目的是希望直接修改
    public void AppNotice(string msg)
    {
    this.Notice.AppendText(msg + "\n");
    }后台一个线程已启动,想更新form2 ,如何才能做到通过调用public void AppNotice(string msg)实现?
    public delegate void UpdateNotice(string NoticeText);//更新notice的委托用
    public event UpdateNotice AppNoticeByThread;void RunThread()
    {
        Debug.Print("thread is run");
        if (AppNoticeByThread != null)
        {
            AppNoticeByThread("new text");
        }
    }
     private void button1_Click(object sender, EventArgs e)
     {
        Thread th = new Thread(new ThreadStart(RunThread));
        th.Start();
     }
    private void Form1_Load(object sender, EventArgs e)
    {
        this.AppNoticeByThread += new UpdateNotice(Form1_AppNoticeByThread);
    }//其他线程改变主线程中的控件状态
     void Form1_AppNoticeByThread(string NoticeText)
    {
        if (textBox1.InvokeRequired)
        {
            textBox1.Invoke(new UpdateNotice(Form1_AppNoticeByThread),new object[]{NoticeText});
        }
        else
        {
            textBox1.Text = NoticeText;
        }
    }
    http://topic.csdn.net/u/20100503/13/0503b79e-8a17-4ea0-98c0-c7f886c77a8b.html?seed=1691679054&r=65144079#r_65144079
      

  2.   


    private delegate void showTime(string timeStr);
    void myEvent_TimeUp(object sender, EventArgs e)
    {
        Times++;
        showTime s = new showTime(ShowTime);
        this.invoke(s, new object[]{Times.toString()});
    }
    private void ShowTime(string times)
    {
       this.label1.Text  = "这是第" + times + "时间到";
    }
    未测试,应该OK的
      

  3.   

    那么如果我是对窗体中的一系列控件的外观进行改变,我不是要处理许多的invoke?并进行许多代理了,这时有好的方法吗?
      

  4.   

            private delegate void CrossThreadOperationControl();        void myEvent_TimeUp(object sender, EventArgs e)
            {
                Times++;
               CrossThreadOperationControl CrossDelete = delegate()
               {
                   this.label1.Text = "这是第" + (Times + 1).ToString() + "时间到";
               };
                label1.Invoke(CrossDelete);
            }
    修改myEvent_TimeUp的实现,就可以了!
      

  5.   

    又见跨线程操作控件。呵呵
    上面的方法都不错
    还有一个
    public Form1(){
    InitializeComponent();
    CheckForIllegalCrossThreadCalls = false;//加上这句就OK了。哈哈
    }
      

  6.   

    这里也只能对label1进行控制,如要大量的修改,如何?
      

  7.   

    要大量?
    把要改的数据定义一个结构体或者类来暂存,然后用SendMessage给自己发送修改消息。
    在defwndproc中拦截消息,读出修改的值,赋给各个控件。
    自己去尝试吧。
      

  8.   

    CheckForIllegalCrossThreadCalls = false;
    禁止:检查非法的跨线程调用
      

  9.   

    如在线程外操作,如何在其它类的事件后处理?
    是否在Event类中增加属性(如TimeUpPro),产生事件时设置其值.再在Form1中利用定时器扫描TimeUpPro,根据对应值作相应的处理呢?
      

  10.   

    CheckForIllegalCrossThreadCalls = false;
    这个方法最简单,如果没有多个线程同时修改的话,就可以用这个了。
    如果有多个线程修改一个控件,就不能这样了,必须做线程同步!
      

  11.   

    Form1中引用了一个类的实例,Form1在此实例的事件触发下动作,来改变窗口中的一些外观,这种情况应是较常见了吧?
    不知有什么好的方法?
      

  12.   

    感谢computerfox(阿捷)!
    我这两次发了贴,你都很快回复了,对我的提问也回答得较充分,谢谢!