跨线程操作无效:

时间:2013-05-11 05:47:12

标签: c# .net winforms

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

所以在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”。

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

4 个答案:

答案 0 :(得分:2)

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

简单的事情;

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

        }));

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

答案 1 :(得分:1)

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

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

答案 2 :(得分:1)

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

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

答案 3 :(得分:0)

更改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);
        }
    }