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

您可以使用调用

// 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
http://msdn.microsoft.com/en-us/library/aa288468(v =vs.71).aspx
Invoke 调用中的匿名方法

于 2012-09-20T07:41:56.110 回答
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 回答
1

在BackgroundWorker 中,当我们调用任何用户控制它的问题时。请在 Window Form Load 事件中使用此属性:

 CheckForIllegalCrossThreadCalls = false;
于 2013-04-04T12:01:03.000 回答
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 控件。

移动

如果 (comboBox15.Text == "")

部分到 button3_click

于 2012-09-20T07:34:04.443 回答