不应该出现的跨线程操作异常

本文关键字:线程 操作 异常 不应该 | 更新日期: 2023-09-27 18:11:36

当我的方法被FileSystemWatcher事件调用时,我在VS2013, WinForms,调试模式上有一个奇怪的Cross-thread operation exception

异常出现在flowLayoutPanel.ResumeLayout();上。

代码是:

public void AddStrategyIcon(StrategyIcon[] icons)
{
    if (flowLayoutPanel.InvokeRequired)
        flowLayoutPanel.Invoke(new Action<StrategyIcon[]>(AddStrategyIcon),
            new object[] {icons});
    else
    {
        flowLayoutPanel.SuspendLayout();
        flowLayoutPanel.Controls.AddRange(icons);
        flowLayoutPanel.ResumeLayout();  // <- Cross-thread op. not valid ...
    }
}

知道为什么会抛出异常以及如何修复它吗?

不应该出现的跨线程操作异常

如果flowLayoutPanel是在UI线程以外的线程上创建的,那么flowLayoutPanel.InvokeRequired将报告如果在相同的非UI线程上调用则不需要调用。

然而,当你调用ResumeLayout(),最终调用函数上的包含控件谁住在UI线程,并引发错误。

找到你调用flowLayoutPanel = new FlowLayoutPanel()的地方,看看它是否被一个不是主UI线程的线程调用。

在方法参数中发现问题。StrategyIcon是一个带有自定义绘图的用户控件。

它崩溃在:

flowLayoutPanel.Invoke(new Action<StrategyIcon[]>(AddStrategyIcon),
    new object[] {icons});

通过将参数更改为DTO(数据传输对象)并将UserControls的实际创建移动到视图来修复此问题:

工作代码:

public void AddStrategyIcon(StrategyIconDto[] dtoList)
{
    if (flowLayoutPanel.InvokeRequired)
        flowLayoutPanel.Invoke(new Action<StrategyIconDto[]>(AddStrategyIcon),
            new object[] {dtoList});
    else
    {
        var controls = new List<Control>();
        foreach (StrategyIconDto dto in dtoList)
            controls.Add((Control) new StrategyIcon(dto));
        flowLayoutPanel.SuspendLayout();
        flowLayoutPanel.Controls.AddRange(controls.ToArray());
        flowLayoutPanel.ResumeLayout();
    }
}