停止在winform按钮单击时执行的功能

本文关键字:执行 功能 单击 按钮 winform | 更新日期: 2023-09-27 17:47:49

  1. 在一个简单的winform应用程序中,我调用了一个函数,该函数在按钮单击事件上无休止地创建文件。我将Application.DoEvents()添加到循环中。

  2. 我按下红色的X关闭表格。

  3. 表单关闭,但文件仍在继续创建。。。

我认为它在按钮线程上,但它不应该是一个背景线程吗?尝试在循环函数上将Thread.CurrentThread.IsBackGround更改为True没有帮助。

想法?

停止在winform按钮单击时执行的功能

使用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组件,或者创建一个不同的线程,并从外部(即从表单)控制它