如何在 C# 中按下停止按钮来停止耗时过长的 UI 线程 [关闭]
Posted
技术标签:
【中文标题】如何在 C# 中按下停止按钮来停止耗时过长的 UI 线程 [关闭]【英文标题】:How can I stop the UI thread that is taking too long with a stop button press in C# [closed] 【发布时间】:2021-11-15 09:23:44 【问题描述】:我有一个 Windows 窗体,其中包含(除其他外)一个开始和停止按钮。如果 Start button_click 代码花费的时间太长,我想按下停止按钮(或其他一些事件),这将允许我停止该代码完成。问题是在 UI 线程允许处理 Stop button_click 代码之前不必等待该代码完成。当我尝试查找问题的答案时,一些线程睡眠、中断和中止信息似乎不适用。一旦按下开始按钮,它就会在我的 Start Button_click 事件处理程序中运行代码,我希望能够启动一个事件,然后停止该代码的运行。我尝试在使用 Async 和 Await 的任务中运行所有代码(在 Start Button_click 事件处理程序中),但这不起作用,因为该代码试图更新和更改我的表单上在主程序中创建的一些文本框用户界面线程。而且由于开始按钮代码需要一段时间才能完成,我不确定如何启动停止事件以允许我停止当前正在运行的代码。
【问题讨论】:
代码总是受欢迎的。 另外,展示您的尝试可以让我们帮助您解决问题。 现在,最好的答案是您需要合作关闭您的代码。CancellationToken
是您所需要的。
【参考方案1】:
执行此操作的正确方法是将任何耗时的代码与更新 UI 的代码分开。可能带有一些接口或适配器类来更新进度或日志记录等内容。
然后您应该在取消的情况下异步运行耗时。如果它受计算限制,则通常使用Task.Run(...)
在后台线程上运行它。要使取消工作,请在启动任务时创建一个TaskCancellationSource
,并将其令牌交给任务。然后任务应定期检查此令牌,例如通过调用ThrowIfCancellation
,只需确保在等待任务时捕获OperationCancelledException
。对于 IO 绑定的任务,您理论上可以这样做,只需将 IO 操作指定为 CancelationToken
,但实际上某些 IO 操作似乎是同步运行的。
然后你的停止按钮可以简单地调用TaskCancellationSource
的取消方法
这可能看起来像很多代码,但如果您希望取消正常工作,这是必需的。
【讨论】:
我尝试将其放入任务中,但由于我想对表单上的某些控件进行更改,它不会让我(来自不同的线程)。所以它甚至不会运行。它出现了 System.InvalidOperationException: 'Cross-thread operation not valid: Control 'dataFileTextBox' 从创建它的线程以外的线程访问。' @mdmenard 正如我所提到的,您必须将 UI 代码与计算代码分开,无论如何这都是一种好习惯。如果您等待任务,您应该回到主线程并可以再次更新 UI。 @mdmenard - 我在 17 小时前询问了代码。您在 8 小时前发布了此评论,但没有代码。但是您的评论专门针对您的部分代码。请通过在您的问题中发布minimal reproducible example 来帮助我们。 @mdmenard - 如果您回答问题,我很乐意重新打开。以上是关于如何在 C# 中按下停止按钮来停止耗时过长的 UI 线程 [关闭]的主要内容,如果未能解决你的问题,请参考以下文章
在 Visual Studio 中按下“停止调试”按钮时拦截信号/事件