不应出现跨线程操作异常

时间:2014-07-05 07:06:13

标签: c# winforms thread-safety

当我的方法被FileSystemWatcher事件调用时,VS2013,WinForms,Debug模式上有一个奇怪的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 ...
    }
}

任何想法为什么抛出异常以及如何解决它?

2 个答案:

答案 0 :(得分:0)

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

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

查找您调用flowLayoutPanel = new FlowLayoutPanel()的位置,并查看是否在不是主UI线程的线程上调用它。

答案 1 :(得分:0)

问题出现在method参数中。 StrategyIcon是带有自定义绘图的UserControl。

崩溃在:

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();
    }
}