【问题标题】:Cross-thread operation not valid, control accessed from thread other than the thread it was created on跨线程操作无效,控制从创建它的线程以外的线程访问
【发布时间】:2013-07-06 06:09:55
【问题描述】:

我收到一个错误"Cross-thread operation not valid: Control 'AllOtherStatus' accessed from a thread other than the thread it was created on."

我有这个代码:_output设置为AllOtherStatus,看调试器,_output.InvokeRequiredfalse

在我更改了一个不使用这段代码的不相关类之前,这段代码运行良好。代码到达 else 语句然后抛出异常。

private void Thread(Object p)
        {
        lock (this)
            {
            if (_output.InvokeRequired)
                {
                if(s!= null)
                    _output.Invoke(new MethodInvoker(delegate { _output.AppendText(s); }));
                }
            else
                _output.AppendText(s);

            s = null;
            }
        }

所以我的问题是,为什么 _output.InvokeRequired 在应该返回 true 时却突然返回 false?

【问题讨论】:

  • AllOtherStatus 是什么类型的控件,它是在哪里创建的?
  • 它是一个TextBox,它是在InitializeComponent();MainForm下的第一行代码中用windows窗体创建的
  • 不,至少我不这么认为。它是在 Windows 窗体中使用设计器创建的。
  • 注释掉lock(this)还会报错吗?
  • 是的,我仍然遇到同样的错误

标签: c# multithreading


【解决方案1】:

在表单加载或线程执行之前的其他地方使用它

     Control.CheckForIllegalCrossThreadCalls = False

【讨论】:

    【解决方案2】:

    来自 MSDN 文档 -

    如果不需要 Invoke,InvokeRequired 可以返回 false(调用 发生在同一个线程上),或者如果控件是在 不同的线程,但尚未创建控件的句柄。

    在尚未创建控件句柄的情况下,您 不应简单地调用控件上的属性、方法或事件。 这可能会导致在后台创建控件的句柄 线程,在没有消息泵的情况下隔离线程上的控件和 使应用程序不稳定。

    您还可以通过检查 当 InvokeRequired 在后台返回 false 时 IsHandleCreated 线。如果尚未创建控制句柄,则必须等待 直到它在调用 Invoke 或 BeginInvoke 之前被创建。 通常,仅当在 应用程序的主要形式的构造函数(如 Application.Run(new MainForm()),在表单显示之前或 Application.Run 已被调用。

    不相关的代码更改可能会延迟创建控制句柄。你能在检查需要调用之前通过显式创建句柄来检查吗 -

    var handle = this.Handle;
    if (_output.InvokeRequired)
    {
      .....
    }
    

    参考答案here。它们可能会引起您的兴趣。

    【讨论】:

    • 我将文本框设置为在创建后立即显示文本,从而解决了问题。
    猜你喜欢
    • 2011-01-15
    • 2016-05-21
    • 2016-06-11
    • 2015-05-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多