【发布时间】:2013-09-06 22:21:22
【问题描述】:
假设我有一个名为 mainFrm 的表单和一个名为 objectA 的对象,该对象包含正在运行的线程。当这两种情况发生时,我的程序应该关闭:
(1). 用户点击 mainFrm 中的“X”按钮(因此引发 mainFrm.FormClosing)
(2). 在 objectA 中引发了一个事件(我们将其命名为“connectionClosed”)
因此,无论是否触发了 (1) 或 (2),此事件链应始终包括:
- 任何对象A 底层线程的终止。 (我已经知道如何 使用位于 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”按钮 -> 表单关闭 -> formclose 被引发 -> 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可能只会上升一次,我现在就去google=)
【问题讨论】:
-
提示:在
connectionClosed,拨打mainFrm.Close()。然后简化为第一种情况。
标签: c# multithreading events formclosing