在一个简单的winform应用程序中,我调用了一个在按钮单击事件上无休止地创建文件的函数。我将Application.DoEvents()添加到循环中。
我按红色X关闭表格。
表单关闭,但文件仍在继续创建......
我认为它在按钮线程上,但不应该是背景线程吗?尝试在循环函数上将Thread.CurrentThread.IsBackGround更改为True无济于事。
想法?
答案 0 :(得分:5)
您使用Application.DoEvents
这一事实是问题的第一个迹象:它表明您在UI线程中做得太多了。它几乎不适合结构良好的程序。 UI线程并不意味着任何长时间运行的任务。 (不可否认,如果绘制你的UI需要很长时间,你几乎没有选择 - 但这表明你应该简化你的用户界面...而且我怀疑它并不适用于这种情况。)
相反,您应该在单独的线程中执行长时间运行的任务(创建文件)。 BackgroundWorker非常适合这种情况 - 您可以使用它将进度报告回UI,并且UI可以调用CancelAsync
方法来请求它停止。您需要检查工作线程中的CancellationPending
属性,以查看是否已请求取消,并正确停止。
编辑:只是为了澄清我认为发生了什么 - 我怀疑你的表格正在关闭,但程序将不会终止,直到事件循环结束。你保持事件循环与文件创建循环一致,因此问题。
请注意,按钮没有线程 - 只有一个用于整个UI。 (在某些情况下,您可能需要多个UI线程,但这种情况很少见 - 如果您已经完成它,您就会知道它。)
答案 1 :(得分:2)
将此表单级变量添加到表单的代码中:
private bool _StillOpen = true;
然后将无限循环代码包装在按钮中,如下所示:
while (_StillOpen)
{
// do whatever your method does
Application.DoEvents();
}
最后,将此代码添加到表单的FormClosing事件中:
_StillOpen = false;
这将允许您在单击关闭按钮时关闭表单。理想情况下,您希望在后台线程上执行此类操作,但此标记方法可能是您当前问题的快速解决方法。
答案 2 :(得分:1)
在UI线程上执行按钮单击处理程序。
当您调用Application.DoEvents时,您将让UI线程处理窗口消息。这样做的一个结果是,每次用户单击该按钮时,单击处理程序方法的新“实例”(堆栈框架)以及许多其他堆栈框架都会添加到堆栈中。像这样:
{windows forms methods incl. message pump}
**ClickHandler**
Application.DoEvents
{windows forms methods incl. message pump}
**ClickHandler**
Application.DoEvents
{windows forms methods incl. message pump}
etc.
这一切都非常可怕。
如果您想在后台运行代码,可以使用更好的替代方法
答案 3 :(得分:0)
您是否为该ButtonClick代码专门创建了一个新线程?如果没有,那么它与表单在同一个线程上,因此“X”按钮应该停止它。
在任何一种情况下,您都可以设置一个标志(isClosing),并在“while true”循环中检查该标志。
答案 4 :(得分:0)
您是否尝试拨打Thread.CurrentThread.Abort()
?
这不是推荐的方法,但如果您无法从函数中访问函数s source code it might help (even though you say you are calling
DoEvents`。
如果您确实可以访问源代码,那么您可以在那里进行检查,让循环知道它必须停止。
此外,您可以使用background worker
组件,或创建不同的线程,并从外部(即从表单)控制它