namespace Httptest
{     public partial class Form1 : Form
    {
        Thread mythread;
        public delegate void mydel();
        public Form1()
        {
            InitializeComponent();
            Mytimer mytimer1=new Mytimer();
           mythread=new Thread(new ThreadStart(Myzhumethod));
         //  mythread.IsBackground = true; //设置后线程会随主线程结束 
            //如存在宿主进程vshost.exe 菜单栏下的 项目-属性-调试-启用调试器,把启用Visual Studio宿主进程这一项取消掉就OK了
           //原因:因为窗口运行的时候创建了前台线程,而前台线程会阻止进程终止,所以即使当窗口关闭但是进程一直无法结束。
            mythread.Start();
            mythread.Suspend();
        }               
        public void Myzhumethod()
        {
            Mytimer mytimer1=new Mytimer();
            mydel mydel1 = new mydel(mytimer1.timecounter);
            this.Invoke(mydel1);
        }
    } public class Mytimer
     {
         public void timecounter()
         {
             int counter = 300;
             int i = 0;
             while (true)
             {
                 Thread.Sleep(1000);
                 counter--;
                 Label3.TextBox = counter.ToString();
                 if (counter == 0)
                 {
       
                     counter = 300;
                 }
             }
         }
     }经高人指点,想把类Mytimer里的 timecounter函数在运行过程中实时将counter值显示在主线程控件Label3中,我用了委托和Invoke,但运行时还报错说 上下文找不到Label3请问我如何修改才能正常使用。

解决方案 »

  1.   

    看了楼主写的东西,就一个感觉,垃圾。逻辑非常混乱。
    以上只是牢骚。Mytimer这个类去哪找Label3?你不给他一个Label3对象他怎么知道Label3是什么东西,我都纳闷了,这是哪个老师教出来的学生,这么基础的东西还犯得着问吗?
      

  2.   

    Label3在哪里定义?一般Invoke的方法是Form的方法,你是new一个对象来invoke,很奇怪,这样应该没用,timecounter应该作用Form的方法,不过看起来很奇怪,我想,你应该把Label3.TextBox = counter.ToString();
     这句提出来作为Form的一个方法,然后在timecounter中用invoke调用它,
      

  3.   

    stonespace兄这么说,我思路明了了很多了,这就改改去
      

  4.   

    你应该想的问题不应该是正确的怎么写,而是正确应该怎么做。
    你想在主线程之外单独开线程做一些事情,这个线程又需要去更新UI。
    因为多线程操作UI可能导致的问题多多,所以进行了限制,不能跨线程操作UI元素。
    在逻辑上就应该是工作线程通过Invoke来更新主线程的内容。
    就说这么多了,本人不喜欢给胶水程序员提供代码,那是一种害人的行为。
      

  5.   

    你线程中调用了this.invoke,invoke在UI线程执行,而且在里面又有while死循环阻塞UI线程在MyTimer中调用Label,这个需要你自己封装一个事件类似定义如下:
        public class Mytimer
        {
            //。
            TimerEventHandler _timer;
            public event TimerEventHandler OnTimer
            {
                add {
                    _timer = value; 
                }
                remove {
                    _timer = null;
                }
            }
            public void timecounter()
            {
            //
                while (!isStop)//设置标志以退出死循环
                {
                    
                    if (_timer != null)
                        _timer(this, new TimerEventArgs(counter));
                    //。
                }
            }
            //。。
        }
        public class TimerEventArgs : EventArgs
        {
            public TimerEventArgs(int _counter)
            {
                counter = _counter;
            }
            public int counter;
        }
        public delegate void TimerEventHandler(object sender, TimerEventArgs e);
    这样你就可以这样使用了:        public void Myzhumethod()
            {
                Mytimer mytimer1 = new Mytimer();
                mytimer1.OnTimer += new TimerEventHandler(mytimer1_OnTimer);//这样调用
                mydel mydel1 = new mydel(mytimer1.timecounter);
                this.Invoke(mydel1);
            }        void mytimer1_OnTimer(object sender, TimerEventArgs e)//看看方便不?
            {
                //必要时候需要label.Invoke
                label1.Text = e.counter.ToString();
            }
      

  6.   

    感谢mngzilin,我好好研究一下,补习一下相关知识
      

  7.   

    另外你不要这样this.invoke
            public void Myzhumethod()
            {
                Mytimer mytimer1 = new Mytimer();
                mytimer1.OnTimer += new TimerEventHandler(mytimer1_OnTimer);//这样调用
                //mydel mydel1 = new mydel(mytimer1.timecounter);
                //this.Invoke(mydel1);
                 mytimer1.timecounter()//直接   
            }或者你在Mytimer中添加启动方法和停止方法,来代替mytimer1.timecounter();这样就更像timer了,不过最好将thread封装到timer中,这样看起来封装更加完整
    public void OnStart()
    {
    isStop=false;
    timecounter();
    }
    public void OnStop()
    {
    isStop=true;
    Sleep(500);
    }
      

  8.   

    查了大量资料,补充了许多委托和事件的知识,勉强把代码实现了。但脑子里乱成一团,委托这块确实有点绕。
    第一:
    在程序执行过程中,真正触发OnTimer事件的实际上是 if (_timer != null)
                        _timer(this, new TimerEventArgs(counter));
    这句么?等于这个自定义事件没法通过OmTimer显示触发?而是靠调用和它绑定的委托对象来触发?第二:
    在_timer(this, new TimerEventArgs(counter));被触发之前,实际上已经做了 mytimer1.OnTimer += new TimerEventHandler(mytimer1_OnTimer);
    也就是说  赋给OnTimer绑定的委托_timer的参数 new TimerEventArgs(counter),同步也赋给了函数mytimer1_OnTimer不然   void mytimer1_OnTimer(object sender, TimerEventArgs e) 的TimerEventArgs e 是如何获得到new TimerEventArgs(counter)的呢?那看来是同时被赋值了
    那是不是可以说 mytimer1.OnTimer 加上多少个附加事件TimerEventHandler,就会在触发_timer(this, new TimerEventArgs(counter));时同步给多少个附加事件的TimerEventArgs e赋值?
      

  9.   

    这些疑问你只需要用reflector反编译一些简单的.net控件就明白了,你不妨试试。
    ===============================================================================
    那是不是可以说 mytimer1.OnTimer 加上多少个附加事件TimerEventHandler,就会在触发_timer(this, new TimerEventArgs(counter));时同步给多少个附加事件的TimerEventArgs e赋值?
    -------------------------------------
    在这个例子中只能绑定一个事件,如果要绑定多个事件需要你修改代码为:
    List<TimerEventHandler> list=new List<TimerEventHandler>()
            public event TimerEventHandler OnTimer
            {
                add {
                    list.Add(value); 
                }
                remove {
                    list.Remove(value);
                }
            }同时修改:
                while (!isStop)//设置标志以退出死循环
                {
                    
                    foreach(TimerEventHandler  h in list)
                       h(this, new TimerEventArgs(counter));
                    //。
                }这样你就可以绑定多个事件,并且同时触发:mytimer1.OnTimer += new TimerEventHandler(mytimer1_OnTimer1);
    mytimer1.OnTimer += new TimerEventHandler(mytimer1_OnTimer2);
    mytimer1.OnTimer += new TimerEventHandler(mytimer1_OnTimer3);