停止在winform按钮单击时执行的功能
本文关键字:执行 功能 单击 按钮 winform | 更新日期: 2023-09-27 17:47:49
-
在一个简单的winform应用程序中,我调用了一个函数,该函数在按钮单击事件上无休止地创建文件。我将Application.DoEvents()添加到循环中。
-
我按下红色的X关闭表格。
-
表单关闭,但文件仍在继续创建。。。
我认为它在按钮线程上,但它不应该是一个背景线程吗?尝试在循环函数上将Thread.CurrentThread.IsBackGround更改为True没有帮助。
想法?
使用Application.DoEvents
是问题的第一个迹象:这表明您在UI线程中做了太多工作。在一个结构良好的程序中,它几乎从来都不合适。UI线程并不意味着有任何长时间运行的任务。(诚然,如果绘制UI需要很长时间,你几乎没有选择——但这表明你应该简化UI……我怀疑这在这种情况下不适用。)
相反,您应该在一个单独的线程中执行长时间运行的任务(创建文件)。BackgroundWorker非常适合这样做——您可以使用它向UI报告进度,UI可以调用CancelAsync
方法来请求它停止。您需要从工作线程中检查CancellationPending
属性,以查看是否已请求取消,然后适当地停止。
编辑:只是为了澄清我认为发生了什么——我怀疑你的表单正在关闭,但在事件循环结束之前,程序不会终止。您在文件创建循环中保持事件循环,因此出现了问题。
请注意,按钮没有线程,整个UI只有一个线程。(在某些情况下,您可能需要多个UI线程,但这种情况很少见,如果您做到了,您就会知道。)
将此表单级别变量添加到表单代码中:
private bool _StillOpen = true;
然后在你的按钮点击中包装无尽的循环代码,如下所示:
while (_StillOpen)
{
// do whatever your method does
Application.DoEvents();
}
最后,将此代码添加到表单的FormClosing事件中:
_StillOpen = false;
这将允许您在单击关闭按钮时关闭表单。理想情况下,您希望在后台线程上执行类似的操作,但这种标记方法可能会快速解决当前问题。
按钮点击处理程序在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.
这一切都很可怕。
如果你想在后台运行代码,更好的选择是使用
- BackgroundWorker组件
- 用于在线程池中运行代码的标准.NET基于委托的机制(BeginInvoke、EndInvoke、IAsyncResult等)
- 如果你想实现一个长时间运行的后台线程,而不是将"大量工作"分配到池中,你可以创建并启动一个线程,它被设置为后台线程
您是否为ButtonClick代码指定了一个新线程?如果不是,那么它与表单在同一个线程上,所以"X"按钮应该停止它。
在任何一种情况下,您都可以设置一个标志(isClosing),并在"whiletrue"循环中检查该标志。
是否尝试调用Thread.CurrentThread.Abort()
?这不是推荐的方式,但如果您无法从函数中访问函数s source code it might help (even though you say you are calling
DoEvents`)。
如果你确实可以访问源代码,那么你可以在那里进行检查,让循环知道它必须停止。
此外,您可以使用background worker
组件,或者创建一个不同的线程,并从外部(即从表单)控制它