1
//button is clicked
//worker starts

private void processWorker_DoWork(object sender, DoWorkEventArgs e)
{
     string code = DoLongWorkAndReturnCode();

     if (code != 0)
     {
         MessageBox.Show("Error!");
         EnableAllButtons(); // this is defined in the other thread and it's where i run into the error.
     }
     else
     {
          string code = DoAnotherLongProcessAndReturnCode(); 
          if (code != 0)
          {
               MessageBox.Show("Error 2!");
               EnableAllButtons(); // again, this is defined in the other thread
          }
     }
}

"EnableAllButtons()" が別のスレッドで定義されているため、クロス スレッド エラーが発生しています。

別のスレッドから、あるスレッドのすべてのボタンを有効にするにはどうすればよいですか?

4

3 に答える 3

2

あなたの名前に基づいて、私はあなたがBackgroundWorkerを使用していると仮定しています。ProgressChangedRunWorkerCompletedControl.Invoke、またはControl.BeginInvokeのいずれかでコントロールを更新する必要があります(ControlのBeginInvokeに対してEndInvokeを起動する必要はありません)。

バックグラウンドワーカーで例外をスローし(0をチェックする以外のコードを使用していない場合、Resultメソッドを使用していない場合)、RunWorkerCompletedイベントに渡されたパラメーターのErrorプロパティをチェックすることをお勧めします。そこから、別のバックグラウンドワーカーを起動するか、停止することができます。メインスレッドで実行されるため、呼び出さずにボタンを変更できます。


例: BeginInvokeを介してボタンを有効にする

この例では、EnableAllButtonsを変更するだけでコードを使用できます。

private void EnableAllButtons() 
{ 
    //See if the main form needs invoke required, assuming the buttons are on the same thread as the form
    if(this.InvokeRequired) 
    {
        //Calls EnableAllButtons a seccond time but this time on the main thread.
        //This does not block, it is "fire and forget"
        this.BeginInvoke(new Action(EnableAllButtons));
    }
    else
    {
        btnProcessImages.Enabled = true; 
        btnBrowse.Enabled = true; 
        btnUpload.Enabled = true; 
        btnExit.Enabled = true; 
        ControlBox = true;
    }
}

例:結果を介してデータを返す

private void processWorker1_DoWork(object sender, DoWorkEventArgs e)
{
     string code = DoLongWorkAndReturnCode();
     e.Result = code;
}
private void processWorkers_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    if (code != 0)
    {
        MessageBox.Show("Error!");
        EnableAllButtons(); // this is defined in the other thread and it's where i run into the error.
    }
    else
    {
          doAnotherLongProcessAndReturnCodesBackgroundWorker.RunWorkerAsync(); 
    }
}

例:例外を介してデータを返す+イベントハンドラーを再利用する。

private void processWorker1_DoWork(object sender, DoWorkEventArgs e)
{
     string code = DoLongWorkAndReturnCode();
     if (code != 0)
     {
         thow new MyCustomExecption(code);
     }
}

private void processWorker2_DoWork(object sender, DoWorkEventArgs e)
{
     string code = DoAnotherLongProcessAndReturnCode(); 
     if (code != 0)
     {
         thow new MyCustomExecption(code);
     }
}

private void processWorkers_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    if(e.Error != null)
    {
        string message;

        //See if it was our error
        if(e.Error.GetType() == typeOf(MyCustomExecption))
        {

            //Choose which error message to send
            if(sender.Equals(processWorker2))
                message = "Error2!";
            else
                message = "Error!";
        }
        else
        {
            //Handle other types of thrown exceptions other than the ones we sent
            message = e.Error.ToString();
        }


        //no matter what, show a dialog box and enable all buttons.
        MessageBox.Show(message);
        EnableAllButtons();
    }
    else
    {
        //Worker completed successfully. 
        //If this was called from processWorker1 call processWorker2

        //Here is the code that was returned from the function
        if(sender.Equals(processWorker1))
            processWorker2.RunWorkerAsync();
    }

}
于 2012-08-27T21:36:57.993 に答える
0

別のスレッドでコントロールにアクセスするには、次の説明に従って Control.Invoke を使用する必要があります: Control.Invoke メソッド (デリゲート)

于 2012-08-27T21:31:40.847 に答える
0

別のスレッドから UI コントロールに直接アクセスする必要がある場合は、この最も便利な拡張メソッドを確認してください。

https://stackoverflow.com/a/3588137/141172

BackgroundWorker は、進行状況の更新のためのイベントを提供します。UI への変更がその性質のものである場合は、そのイベントの使用を検討してください。

于 2012-08-27T21:33:26.000 に答える