none
自己创建的一个类,有个backgroundworker变量。为什么多线程中可以调用控件。。 RRS feed

  • 问题

  • public partial class Component1 : SerialPort
    {  
          private System.ComponentModel.BackgroundWorker backgroundWorker1;
          private System.Windows.Forms.TextBox textBox1;
          //多余的就不写了。。
          private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
            {
                while (true)
                {
                    textBox1.Text = "_PoolUntil";
                }
            }
    }

    为什么他能这样做,其实这样是错误的。他却可以正常运行。
    发现他不能调用Invoke这个函数,如果调用就会出现
    "在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke。"
    2009年5月14日 15:44

答案

全部回复

  • 你好,
    1.如果在执行 RunWorkerAsync() 之前没有把 textBox 加入到 From.Controls 中那是正确的,如果RunWorkerAsync() 之前已执行了 Form.Controls.Add(textBox1) 那上面的代码是错的
    2. 不能调用 Invoke 是因为 textBox1 是在UI线程中创建的, 如果你把 textBox1  创建的代码写到 DoWork 中那执行就没有问题了, Invoke 必须在创建控件的线程上使用

    知识改变命运,奋斗成就人生!
    2009年5月14日 16:09
    版主
  • 你好,
    1.如果在执行 RunWorkerAsync() 之前没有把 textBox 加入到 From.Controls 中那是正确的,如果RunWorkerAsync() 之前已执行了 Form.Controls.Add(textBox1) 那上面的代码是错的
    2. 不能调用 Invoke 是因为 textBox1 是在UI线程中创建的, 如果你把 textBox1  创建的代码写到 DoWork 中那执行就没有问题了, Invoke 必须在创建控件的线程上使用

    知识改变命运,奋斗成就人生!

    textbox1不是在form建立的,是不是没办法controls.add呢。??
    2009年5月15日 1:18
  • 你是想在什么时候 Add textbox1
    知识改变命运,奋斗成就人生!
    2009年5月15日 1:20
    版主
  • 你是想在什么时候 Add textbox1
    知识改变命运,奋斗成就人生!

    public partial class Component1 : SerialPort
    {  
          private System.ComponentModel.BackgroundWorker backgroundWorker1;
          private System.Windows.Forms.TextBox textBox1;
          //多余的就不写了。。
          private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
            {
                while (true)
                {
                    textBox1.Text = "_PoolUntil";
                }
            }
    }

    在这个类中,应该没办法add吧。是否能够用此类的本身的invoke功能??
    2009年5月15日 1:23
  • 你可以在 backgroundWorker1_WorkComplate 事件中添加,this.Controls.Add(textBox1); WorkComplate 是异步执行完毕的事件
    知识改变命运,奋斗成就人生!
    2009年5月15日 1:26
    版主
  • 你可以在 backgroundWorker1_WorkComplate 事件中添加,this.Controls.Add(textBox1); WorkComplate 是异步执行完毕的事件
    知识改变命运,奋斗成就人生!

    谢谢,在这个类中,没有this.controls这个东东。。
    2009年5月15日 1:28
  • 哦,我以为是 from, 你可以通过这个类显示的容器控件.Controls.Add(...), 如果这个类不用于显示,那可以把 textBox, 改为 string 变量,不用于显示的话用 textbox 意议不大
    知识改变命运,奋斗成就人生!
    2009年5月15日 1:31
    版主
  • 哦,我以为是 from, 你可以通过这个类显示的容器控件.Controls.Add(...), 如果这个类不用于显示,那可以把 textBox, 改为 string 变量,不用于显示的话用 textbox 意议不大
    知识改变命运,奋斗成就人生!

    我想跑到主线程中,,所以用string,,不行,,无法跑到主线程中。。试下用一个panel看看,,
    2009年5月15日 1:34
  • DoWork 事件中的代码是新线程中执行的
    WorkComplate 事件中的代码块就是在 UI 线程中执行的
    知识改变命运,奋斗成就人生!
    2009年5月15日 1:36
    版主
  • DoWork 事件中的代码是新线程中执行的
    WorkComplate 事件中的代码块就是在 UI 线程中执行的
    知识改变命运,奋斗成就人生!

    不想运行结束,要一直while..谢谢
    2009年5月15日 1:37
  • 这样是不行的
    知识改变命运,奋斗成就人生!
    2009年5月15日 1:39
    版主
  • 这样是不行的
    知识改变命运,奋斗成就人生!

    我把form1本身做成参数传进去了,,有点奇怪就是了,,哈
    2009年5月15日 2:16
  • 这样是不行的
    知识改变命运,奋斗成就人生!

    我把form1本身做成参数传进去了,,有点奇怪就是了,,哈

    运行是成功了,效果一样,只是。。。。。非常不合理
    2009年5月15日 3:36
  • 怎么不合理?
    知识改变命运,奋斗成就人生!
    2009年5月15日 3:37
    版主
  • 怎么不合理?
    知识改变命运,奋斗成就人生!

    运行时完全是正常的,但是退出的时候,1/4的机率整个程序会死在那里,只有界面,什么都动不了。。。。
    2009年5月15日 5:58
  • 这里地说明可能会有一些帮助:
    http://msdn.microsoft.com/en-us/library/system.windows.forms.control.invokerequired.aspx

    我猜InvokeRequired应该使用线程本地存储实现的。
    2009年5月15日 6:03
  • http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx
    这个例子很全,看看吧

    知识改变命运,奋斗成就人生!
    2009年5月15日 6:12
    版主
  • http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx
    这个例子很全,看看吧

    知识改变命运,奋斗成就人生!

    谢谢,真的很头疼的说。。
    2009年5月15日 6:14
  • http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx
    这个例子很全,看看吧

    知识改变命运,奋斗成就人生!

    应该算是找到比较完整的问题所在
    invoke不能放在lock里面
    lock(this)
    {
    invoke这句运行时是对的,退出时就会有麻烦。。。感觉是这样,,不太清楚
    }
    2009年5月15日 6:15