none
多线程中事件响应函数属于哪个线程 RRS feed

  • 问题

  • void x_DataReceive(HttpWebClient Sender, DownLoadEventArgs e){
    
         this.labelREsult.Text = "已接收到: " + e.Data.Length.ToString() + "字节";
    }
    
    

    代码类似上面,由另一个线程触发,这个事件。我想问的是,触发事件后,不是临时新开一个临时线程处理事件吗?另外,这个事件响应函数是属于哪个线程的,是属于触发线程,还是界面线程,还是属于临时线程(如果有新开事件临时线程的话)。是用this.Invoke还是什么办法能解决?

    我开了额外的5个线程。我的程序在Visual Studio 调试肯定死,VS捕获不到错误,直接系统捕获然后无法响应,只能程序强制关闭;不用VS不一定会死,在下载http://localhost/example.flv 时不会死,进度条满格,而且下载的达20多MB的视频可以看,经验证没有数据错误。资源只在真正下载网络上http://www...类的资源会死,而且进度条显示没有接收到哪怕0%的数据。 

    补充,后来用强制加断点捕捉到“在不是创建
         this.labelREsult的线程访问控件”.

    补充问题:“在不是创建
         this.labelREsult的线程访问控件”,我发现如果直接在另一个线程只读取控件时,不会出现这个错误;这个错误往往在另一个线程试图修改该控件的值时会发生。问题是,有时发现这个规律不一定,有时甚至只读也会出错。Why?

    • 已编辑 physics_fqh 2010年4月12日 2:36 编辑行数
    2010年4月12日 2:22

答案

全部回复

  • 你好!

    线程中操作 UI 线程创建的控件,需要使用 Control 的 BeginInvode 或 Invoke 方法。如下:

    public delegate void ClientDelegate();
    void x_DataReceive(HttpWebClient Sender, DownLoadEventArgs e)
    {
        this.BeginInvode(delegate { this.labelREsult.Text = "已接收到: " + e.Data.Length.ToString() + "字节"; });
    }

    另外通过 System.Threading.Thread.CurrentThread 获取当前线程。


    知识改变命运,奋斗成就人生!
    2010年4月12日 5:09
    版主
  • 不能在非创建控件的线程中访问此控件。如果需要更新界面的话,唯一的方法就是this.Invoke()。

    至于规律……对于没有handle的控件来说,只读取属性应该是没有问题的


    共同努力,共同提高
    kaedei#live.cn My BLOG
    2010年4月12日 14:36
  • 你好 你也可以通过设置Control.CheckForIllegalCrossThreadCalls属性为false 即可跨线程调用

    但是更好的解决方案是用BeginInvoke或者Invoke方法


    I see you~http://hi.baidu.com/1987raymondMy Blog~~~
    • 已标记为答案 physics_fqh 2010年4月13日 23:33
    2010年4月13日 12:19
    版主
  • Control.CheckForIllegalCrossThreadCalls 一项这个还真不知道,我之前想过是否有类似的方法。我的问题已经解决了。感谢各位!

    原来我测试的地址,它的服务器不支持过多的线程下载,我把线程数改为2,就顺利下载了。另外在

    C#中的委托和事件(续) 中,似乎表明,一般地触发事件时,发布者会在它的线程里执行订阅的代码,发布者被阻塞,就是说这时订阅的函数属于触发函数所在的线程。而如果调用BeginInvoke的话,发布者不会被阻塞,订阅的函数会异步执行,即临时开线程(线程池)队列等待处理;EndInvoke也类似。

    2010年4月13日 23:46