-1

私のアプリケーションでは、保留中のアプリケーションについてユーザーに通知する必要がありました。

そのため、データベースにクエリを実行して保留中のアプリケーションを取得し続けるmdiParentを設定し、見つかった場合はツールチップに表示しますBackgroundWorkerMdiParent

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' は、それが作成されたスレッド以外のスレッドからアクセスされました。

2 つの異なるスレッドが原因であることは理解していますが、これを整理することはできません。誰でも解決策を提案できますか? 関連する質問で読んだアイデアを試しましたが、正しい解決策が見つかりません

4

4 に答える 4

2

外部スレッド (バックグラウンド ワーカーは別のスレッドで操作を実行します) からコントロールにアクセスするときはいつでも、何らかの呼び出しを行う必要があります。これにより、基になるウィンドウ ハンドルを所有するスレッドでデリゲートが実行されます。

のような単純なもの;

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

        }));

前のコードがコントロールにアクセスしていない限り、おそらくあなたのケースでうまくいくでしょう。私は何をしているのかわかりませんgetnotification()

于 2013-05-11T06:18:40.547 に答える
1

ワーカー スレッドの UI (ツールヒント) を変更しています。

それは許されません。ウィンドウで Invoke を呼び出し、ツールヒントを変更する関数にデリゲートを渡すことにより、UI スレッドを使用してツールヒントを変更します。

于 2013-05-11T06:05:38.423 に答える
1

ツールチップの変更はワーカー スレッドの正確な最後で発生するように見えるため、RunWorkerCompletedイベントを使用できます。そこから UI スレッドを変更できます。このイベントはそのために設計されています。

もちろん、Chris Bucklers のInvokeソリューションも機能します。

于 2013-05-11T06:29:36.310 に答える
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);
        }
    }
于 2013-05-11T09:07:07.087 に答える