none
如何跨线程调用windows窗体控件?

    问题

  • 当窗体(Main)收到服务端发来的消息时,要求客户端退出(类似于QQ在别处登录,自己被迫下线一样),关闭窗体

    我在窗体收到消息的事件中,直接使用了Me.Close(),试图关闭窗体

        Public Sub SayToUser() Implements CallBackService.ICallback.SayToUser
                     MessageBox.Show("该用户已在别处登录,您将被迫退出!", "系统消息", MessageBoxButtons.OK, MessageBoxIcon.Warning) 

                      Me.Close()

      End Sub
     

    但出现错误:

    线程间操作无效: 从不是创建控件“Main”的线程访问它

    看了msdn中的相关说明,道理似乎明白,可就是不会用(真不好意思!)

    求高手给个具体的代码吧!


    韩立学





    2016年7月13日 9:32

答案

  • 这个问题有很多解决方案,部分方法如下

    1 OnLoad中调用 Control.CheckForIllegalCrossThreadCalls = false;  其它的代码不用修改 
    2 使用一个Control.Invoke,例子 SetTextCallback 是一个带一个字符串参数的自定义委托

    delegate void SetTextCallback(string text);

    private void SetText(stringtext)
     {

    if (this.textBox1.InvokeRequired)

    {
       SetTextCallback d = new SetTextCallback(SetText);
        this.Invoke(d, new object[] { text });
    }
    else
    {
        this.textBox1.Text = text;
     }
    }
    3 使用BackgroundWorker
    private void setTextBackgroundWorkerBtn_Click( object sender, EventArgs e)

    {
    this.backgroundWorker1.RunWorkerAsync();
    }

    private void backgroundWorker1_RunWorkerCompleted(object sender,RunWorkerCompletedEventArgs e)
    {
    this.textBox1.Text = "This text was set safely by BackgroundWorker.";
    }


    专注于.NET ERP/CRM开发框架,C/S架构,SQL Server + ORM(LLBL Gen Pro) + Infragistics WinForms


    2016年7月13日 10:03

全部回复

  • 这个问题有很多解决方案,部分方法如下

    1 OnLoad中调用 Control.CheckForIllegalCrossThreadCalls = false;  其它的代码不用修改 
    2 使用一个Control.Invoke,例子 SetTextCallback 是一个带一个字符串参数的自定义委托

    delegate void SetTextCallback(string text);

    private void SetText(stringtext)
     {

    if (this.textBox1.InvokeRequired)

    {
       SetTextCallback d = new SetTextCallback(SetText);
        this.Invoke(d, new object[] { text });
    }
    else
    {
        this.textBox1.Text = text;
     }
    }
    3 使用BackgroundWorker
    private void setTextBackgroundWorkerBtn_Click( object sender, EventArgs e)

    {
    this.backgroundWorker1.RunWorkerAsync();
    }

    private void backgroundWorker1_RunWorkerCompleted(object sender,RunWorkerCompletedEventArgs e)
    {
    this.textBox1.Text = "This text was set safely by BackgroundWorker.";
    }


    专注于.NET ERP/CRM开发框架,C/S架构,SQL Server + ORM(LLBL Gen Pro) + Infragistics WinForms


    2016年7月13日 10:03
  • 谢谢回复!

        用了    CheckForIllegalCrossThreadCalls = False,问题解决了,但总得似乎应该寻求第2、3种方法,Me.Close该怎么实现?


    韩立学


    2016年7月13日 10:45