2013-02-25 94 views
0

我已经制作了一个示例程序,它在后台线程上生成每秒2000个整数,当它结束时它会触发一个事件,它从随机生成的数据在GUI上绘制图形(我有在我的线程内模拟真实测量的睡眠)。从后台访问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'。

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

+3

推荐的方法是不让表单关闭,直到完成所有后台线程。例如禁用关闭黄油,或重写关闭事件以通知用户当前正在背景中发生的事情,并稍后再试。否则,如果让表单关闭,它将在后台处理仍然发生时消失... – 2013-02-25 23:46:09

+0

现在我正在检查Thread.IsAlive布尔值,但是如果它返回true并且我调用thread.Join() - 程序冻结,没有任何反应。 – patex1987 2013-02-26 00:07:25

+0

你在哪里调用thread.join?如果你在表单关闭时调用它,它会阻塞,直到你的后台线程完成 - 这就是Join所做的。 – 2013-02-26 00:14:18

回答

0

解决方案可能是检查IsDisposed。事情是这样的:

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

    // ... 
} 
+0

对不起,但它似乎并没有解决问题。同样的事情发生之前像 – patex1987 2013-02-26 00:02:56

1

您已经关闭了形式,但线程仍在运行,所以当它完成它试图调用一个方法释放的对象上。你的表格。

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

不要被诱惑杀死它。非常不好的习惯,你不想进入那个。

+0

在Form.FormClosed事件我正在检查Thread.IsAlive状态。当它返回true时,我试图Join()线程(或者是否有任何其他方式来等待线程完成其任务?),因为调用Join方法时整个程序会冻结。 – patex1987 2013-02-26 00:10:55

+0

加入会等待,但它会冻结你的主线程。线程是否在完成时终止。如果不是这样,直到你发出信号才会结束。 – 2013-02-26 00:28:54

+0

如何在完成时终止线程? – patex1987 2013-02-26 00:30:09

1

正确的做法,看起来很丑陋,很可能是抓住了异常并吞下它。表单的Dispose可能不合理,直到后台线程退出(这种情况很容易导致死锁);框架也没有提供任何方法,说明在控件或表单上尝试使用这种方法,但是如果它被丢弃,则什么都不做。因此,你最好的办法是编写TryInvokeTryBeginInvoke方法,通过捕获任何异常,如果表单已被处置,将会这样做。您可以在这种方法中使用IsDisposed检查,但您应该认识到,由于某些Framework怪癖,有些竞争条件无法很好地解决。