假设我有一个名为 mainFrm 的表单和一个名为 objectA 的对象,该对象包含正在运行的线程。当这两种情况发生时,我的程序应该关闭:
(1)。用户单击 mainFrm 中的“X”按钮(因此引发 mainFrm.FormClosing)
(2)。在 objectA 中引发了一个事件(我们将其命名为“connectionClosed”)
因此,无论是否触发(1)或(2),此事件链应始终包括:
- 任何对象的终止底层线程。(我已经知道如何使用位于 objectA 中的代码优雅地终止它们)
- 当然,mainFrm 的关闭
解决这个问题的最佳方法是什么?
我就是这样解决的
不知道为什么这个问题没有得到社区的好评。我认为这是相当清晰和直接的。这是我解决它的方法,我希望这也有助于更好地定义我的意思。如果您有任何其他疑问,请告诉我 =)
在表单类中:
...
this.FormClosed += objectA.kill;
objectA.connectionClosed +=closeForm;
...
private void closeForm(object sender, FormClosedEventArgs e)
{
try
{
this.Invoke(new MethodInvoker(delegate { this.Close(); }));
}
catch { }
}
在 objectA 的类中:
...
//connectionClosed is raised in different parts of objectA's threads code
connectionClosed += killClient;
...
public void killClient(object sender, FormClosedEventArgs e)
{
//event should go past this point just once
if (!_connectionClosed)
{
_connectionClosed = true;
try
{
... //close connection killing all threads
}
catch { }
}
}
根据开头所述的 (1) 和 (2) 用例,这就是应该发生的事情(如果我没记错的话)
(1)。用户单击“X”按钮 -> 表单关闭 -> formclosed 被引发 -> objectA.kill 方法委托被执行 -> 内部线程引发一些 connectionClosed 事件,这将触发更多 objectA.kill 执行,但这不会造成任何损害,这要归功于volatile bool _connectionClosed (当然,因为有一个 try/catch 无论如何都可以工作,但对我来说不再执行此类代码更有意义)-> 线程由 objectA.kill 的唯一完全执行终止-> SUCCESS
(2)。服务器关闭连接或网络错误 -> objectA 的内部线程检测到连接错误并引发多个 connectionClosed 事件 -> 不同的线程将尝试执行 objectA.kill 方法委托。-> 同时,在主窗体中,closeForm 被执行,关闭窗体 -> 这也触发了另一个 objectA.kill 执行(感谢 this.FormClosed += _client.killClient; ) -> 再次,这不会造成伤害,因为 _connectionClosed volatile bool 将只让一个线程实际执行代码(引发事件的第一个)-> 线程通过 objectA.kill 的唯一完整执行优雅地终止-> SUCCESS
下一步应该是找到一种更方便的方法,以便 connectionClosed 可能只上升一次,我现在就去谷歌搜索 =)