为什么我没有拿到"跨线程操作无效"错误线程、错误、操作、QUOT

2023-09-04 10:02:48 作者:许卿白头上上签

我用一个BackgroundWorker而做到这一点:

 私人无效loadNewAsyncToolStripMenuItem_Click(对象发件人,EventArgs的)
{
    this.Text =的RunWorkerAsync();
    backgroundWorkerLoading.RunWorkerAsync();
}
私人无效backgroundWorkerLoading_DoWork(对象发件人,DoWorkEventArgs E)
{
    UnsafeThreadMethod(你好);
    EvenUnsaferThreadMethod();
}
 

而现在的两种方法。

 私人无效UnsafeThreadMethod(文本字符串)
{
    toolStripLabelRssFeedData.Text =文本;
}

私人无效EvenUnsaferThreadMethod()
{
    panelLoading.Visible = TRUE;
}
 

我不明白为什么 UnsafeThreadMethod 不抛出以下异常,但 EvenUnsaferThreadMethod 确实

  

跨线程操作无效:控制'panelLoading'从一个线程比其他访问>发其创建

据该消息是因为 toolStripLabelRssFeedData 是在同一线程创建的,但事实并非如此。

我想,我不能调用由主线程创建的控件并使用 ProgressChanged 事件。这是怎么回事?

ucrtbased.dll 将一个无效参数传递给了将无效参数视为严重错误的函数

和我有一个第二个问题。什么是做这样的时候,我可以利用的优势 ProgressChanged ?我该怎么办?

 私人无效EvenUnsaferThreadMethod()
{
    如果(panelLoading.InvokeRequired)
    {
        panelLoading.Invoke(新MethodInvoker(()=> {EvenUnsaferThreadMethod();}));
    }
    其他
    {
        panelLoading.Visible = TRUE;
    }
}
 

解决方案

要第一个问题:

在跨线程异常被抛出故意在调试模式下。这意味着有(有条件)code检查的InvokeRequired内置到大多数GUI控件。像面板。

显然,ToolstripLabel不作此检查。因为它不从控制派生,可能是因为它是这个安全网的范围之外。

由于标准的声明任何实例成员都不能保证是线程安全的适用于ToolstripLabel设置文本时,我只想去与正常InvokeRequired逻辑。

I use a BackgroundWorker and do this:

private void loadNewAsyncToolStripMenuItem_Click(object sender, EventArgs e)
{
    this.Text = "RunWorkerAsync()";
    backgroundWorkerLoading.RunWorkerAsync();
}
private void backgroundWorkerLoading_DoWork(object sender, DoWorkEventArgs e)
{
    UnsafeThreadMethod("hello");
    EvenUnsaferThreadMethod();
}

And now the two methods.

private void UnsafeThreadMethod(string text)
{
    toolStripLabelRssFeedData.Text = text;
}

private void EvenUnsaferThreadMethod()
{
    panelLoading.Visible = true;
}

I don't understand why UnsafeThreadMethod doesn't throw the following exception but EvenUnsaferThreadMethod does.

Cross-thread operation not valid: Control 'panelLoading' accessed from a thread other than the > thread it was created on.

According to the message it's because toolStripLabelRssFeedData was created on the same thread but it wasn't.

I thought that I can't call controls created by the main thread and have to use the ProgressChanged event. What's going on?

And I have a second question. What is the advantage of doing it like this when I can use ProgressChanged? What should I do?

private void EvenUnsaferThreadMethod()
{
    if (panelLoading.InvokeRequired)
    {
        panelLoading.Invoke(new MethodInvoker(() => { EvenUnsaferThreadMethod(); }));
    }
    else
    {
        panelLoading.Visible = true;
    }
}

解决方案

To the first question:

the cross-thread exception is deliberately thrown in Debug mode. This means there is (conditional) code checking on InvokeRequired built into most of the GUI controls. Like the Panel.

Apparently the ToolstripLabel does not make this check. Since it does not derive from Control that could be because it is outside the scope of this safety net.

Since the standard disclaimer "Any instance members are not guaranteed to be thread safe" applies to the ToolstripLabel I would just go with the normal InvokeRequired logic when setting the Text.