【问题标题】:Cross-thread operation not valid: [duplicate]跨线程操作无效:[重复]
【发布时间】:2013-05-11 17:11:48
【问题描述】:

在我的应用程序中,我需要通知用户有关待处理的应用程序。

所以在mdiParent 中,我设置了一个BackgroundWorker,它不断查询数据库以获取任何待处理的应用程序,如果找到任何待处理的应用程序,则将其显示在MdiParent 的工具提示上

private void button1_Click(object sender, EventArgs e)
{
    backgroundWorker1.RunWorkerAsync(2000);
}

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    fillnotification();
}    

public void fillnotification()
{
    int pending = 0;
    if( Program.USERPK != 0)
    {    
        DataTable dt = nftrans.getnotification();
        pending = dt.Rows.Count;

        String message = "You Have  " + pending + " Applications Pending For Approval";

        // toolTip1.SetToolTip(lblStatus , message);
        toolTip1.Show(message , this, lblStatus.Location);
    }
}

但是当我运行解决方案时,我遇到了一个异常:

跨线程操作无效:控件“MainForm”从创建它的线程以外的线程访问。

我理解这是由于两个不同的线程,但无法解决这个问题。任何人都可以提出解决方案吗?我尝试了在相关问题中阅读的想法但找不到正确的解决方案

【问题讨论】:

  • 是的winform应用程序
  • 至少看看其他成千上万个相同的问题,然后再问同样的问题?请问?
  • 我检查了 qstns 但我找不到与工具提示相关的任何人

标签: c# .net winforms


【解决方案1】:

任何时候您从外部线程(后台工作线程Executes an operation on a separate thread.)访问控件时,您都需要进行某种调用。这会在拥有底层窗口句柄的线程上执行一个委托。

一些简单的东西,比如;

        this.Invoke(new MethodInvoker(delegate()
        {
        //   toolTip1.SetToolTip(lblStatus , message);
        toolTip1.Show(message, this, lblStatus.Location);

        }));

可能适用于您的情况,只要您以前的代码不访问控件,我不确定 getnotification() 在做什么。

【讨论】:

    【解决方案2】:

    您正在更改工作线程上的 UI(工具提示)。

    这是不允许的。使用 UI 线程通过在 Window 上调用 Invoke 并将委托传递给更改工具提示的函数来更改工具提示。

    【讨论】:

      【解决方案3】:

      由于似乎工具提示的更改发生在您的工作线程的确切末尾,您可以使用RunWorkerCompleted 事件 - 您可以从那里修改 UI 线程,这就是该事件的设计目的。

      当然,Chris Bucklers Invoke 解决方案也可以。

      【讨论】:

        【解决方案4】:

        更改 fillnotification() 以返回您的待处理值并将其传递给 DoWork() 处理程序中的“e.Result”。现在连接 RunWorkerCompleted() 事件并检索后台操作的结果:

            private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
            {
                e.Result = fillnotification();
            }
        
            public int fillnotification()
            {
                if (Program.USERPK != 0)
                {
                    DataTable dt = nftrans.getnotification();
                    return dt.Rows.Count;
                }
                return -1;
            }
        
            private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
            {
                int pending = (int)e.Result;
                if (pending != -1)
                {
                    String message = "You Have  " + pending.ToString() + " Applications Pending For Approval";
                    toolTip1.Show(message, this, lblStatus.Location);
                }
            }
        

        【讨论】:

          猜你喜欢
          • 2012-08-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-12-04
          • 1970-01-01
          • 1970-01-01
          • 2011-03-27
          相关资源
          最近更新 更多