【问题标题】:Accessing the GUI from a background Thread从后台线程访问 GUI
【发布时间】:2013-02-25 23:39:47
【问题描述】:

我制作了一个示例程序,它在后台线程上每秒生成 2000 个整数,当它完成时,它会触发一个事件,该事件会根据随机生成的数据在 GUI 上绘制图形(我的线程中有一个睡眠来模拟实际测量)。

private void SetChart(System.Windows.Forms.DataVisualization.Charting.Series series)
{
  if (InvokeRequired)
  {
    SetChartCallback d = new SetChartCallback(SetChart);
    this.Invoke(d, new object[] { series });
  }
  else
  {
    chart1.Series[0] = series;
    chart1.Series[0].Name = "Generated Data";
  }
}

我在 MSDN 网站上找到了这种方法。它工作正常,唯一的问题是,当我关闭应用程序时。有时会出现错误消息:

无法访问已处置的对象。
对象名称:“Form1”。

当我关闭程序时它会处理所有元素,我怎样才能防止这个错误不发生?

【问题讨论】:

  • 推荐的方法是在所有后台线程都完成之前不要关闭表单。例如禁用关闭黄油,或覆盖关闭事件以通知用户当前正在后台发生某些事情并稍后重试。否则,如果您让表单关闭,它将在后台处理仍在进行时消失...
  • 现在我正在检查 Thread.IsAlive 布尔值,但如果它返回 true 并且我调用 thread.Join() - 程序将冻结并且没有任何反应。
  • 你在哪里调用thread.join?如果你在表单的结尾调用它,它将阻塞,直到你的后台线程完成——这就是 Join 所做的。
  • 是的,我在表单结束时调用它(FormClosed 事件)。这是我想要在程序关闭之前完成这个线程的目标,但是 Join() 没有帮助,程序冻结并且它永远不会关闭。
  • 对不起,你是对的,它调用了方法。我明天会在这里发帖。

标签: c# multithreading dispose invoke


【解决方案1】:

您已关闭表单,但线程仍在运行,因此当它完成时,它会尝试调用已处置对象上的方法。你的表格。

您可以等待线程完成。 或者您可以以某种方式向它发出信号以停止创建您不再需要的整数并立即退出它的循环。

不要试图杀死它。非常坏的习惯,你不想这样做。

【讨论】:

  • 在 Form.FormClosed 事件中,我正在检查 Thread.IsAlive 状态。当它返回 true 时,我正在尝试 Join() 线程(或者是否有任何其他方法可以等待线程完成其任务?),因为调用 Join 方法整个程序都会冻结。
  • Join 会等待,但它会冻结你的主线程。线程是否在完成时终止。如果不是,它永远不会完成,直到你发出信号。
  • 这是默认设置。可能值得发布您的线程创建和启动代码。
【解决方案2】:

正确的方法,虽然看起来很丑陋,但可能是捕获异常并吞下它。表单的Dispose 阻塞直到后台线程退出可能是不合理的(这种情况很容易导致死锁);框架也没有提供任何方法说尝试在控件或表单上使用InvokeBeginInvoke 此方法,但如果它已被处置,则根本不做任何事情。因此,您最好的选择可能是编写TryInvokeTryBeginInvoke 方法,这将通过捕获表单已被处理时产生的任何异常来实现。您可以在此类方法中使用IsDisposed 检查,但您应该意识到,由于某些框架怪癖,有些竞争条件无法很好地解决。

【讨论】:

    【解决方案3】:

    一个解决方案可能是检查 IsDisposed。像这样的:

    private void SetChart(System.Windows.Forms.DataVisualization.Charting.Series series)
    {
        if (IsDisposed)
           return;
    
        // ...
    }
    

    【讨论】:

    • 对不起,但似乎并没有解决问题。和以前一样
    猜你喜欢
    • 1970-01-01
    • 2012-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多