3

以下は私のコーディングです:

    Form2 msgForm;
    private void button3_Click_1(object sender, EventArgs e)
    {

        bw.WorkerReportsProgress = true;
        bw.WorkerSupportsCancellation = true;
        bw.DoWork += new DoWorkEventHandler(bw_DoWork);
        //bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
        bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);

        msgForm = new Form2();

        try
        {
            bw.RunWorkerAsync();

            msgForm.ShowDialog();
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }

    void bw_DoWork(object sender, DoWorkEventArgs e)
    {
        if (comboBox15.Text == "")
        {
            //MessageBox.Show("Please select Printer ID.", "Status", MessageBoxButtons.OK, MessageBoxIcon.Error);
            //return;
        }
        // Coding that transmit protocol and will last around 2 minutes.
    }

    void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        msgForm.Close();
    }

このバックグラウンド ワーカー コーディングを実行すると、「クロススレッド操作が無効です: コントロール 'comboBox15' は、それが作成されたスレッド以外のスレッドからアクセスされました。」というエラーが表示されます。

この問題を解決するにはどうすればよいですか?

4

5 に答える 5

5

Invokeを使用できます:

// InvokeRequired required compares the thread ID of the
// calling thread to the thread ID of the creating thread.
// If these threads are different, it returns true.
if (this.comboBox15.InvokeRequired)
{
    this.Invoke((MethodInvoker) delegate {if (comboBox15.Text == ""){// What you want to do}});
}
else
{
    if (comboBox15.Text == "")
    {
    }
}

次もお読みください:
http://msdn.microsoft.com/en-us/library/ms171728(v=vs.80).aspx
=vs.71).aspx
Invoke 呼び出しの匿名メソッド

于 2012-09-20T07:41:56.110 に答える
1

BackgroundWorker では、任意のユーザーを呼び出すと、その問題が制御されます。Window Form Load イベントでこのプロパティを使用してください:

 CheckForIllegalCrossThreadCalls = false;
于 2013-04-04T12:01:03.000 に答える
1

非 UI スレッドから UI 要素を取得することはできません。理想的には、開始前に関連情報をバックグラウンド ワーカーに提供します。

string text = combo15.Text;
bw.DoWork += (sender, args) => TransmitStuff(combo15.Text, args);

...

void TransmitStuff(string printerId, DoWorkEventArgs e)
{
    ...
}

.NET 4.5 と C# 5 を使用できる場合は、非同期メソッドを使用してこれらすべてを簡単にすることができますが、それが選択肢になる可能性は低いと思います。

編集: を使用することはできInvokeますが、それは非常に面倒です-そして、一貫性のない状態になる可能性があります。私は通常、長期実行オペレーションを開始する前に必要なすべての状態を解決し、すべてを検証してから、オペレーションに渡す方が整頓されていると考えています。操作中に UI を更新する必要がある場合は、BackgroundWorker進行機能を使用できます。

于 2012-09-20T07:34:20.297 に答える
0

以下のような値を渡すことで回避できます。

private void Dowork()
{
    backgroundWorker1.RunWorkerAsync(comboBox1.Text);
}

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    String selected = (String)e.Argument;
    if (String.IsNullOrEmpty(selected)) return;
    //do stuff
}
于 2012-09-20T07:38:24.597 に答える
0

メインスレッドからのみ GUI コントロールにアクセスできます。

移動

if (comboBox15.Text == "")

part から button3_click

于 2012-09-20T07:34:04.443 に答える