C#等待线程完成而不阻塞UI [重复]
Posted
技术标签:
【中文标题】C#等待线程完成而不阻塞UI [重复]【英文标题】:C# wait for thread to finish without blocking UI [duplicate] 【发布时间】:2021-05-19 18:56:36 【问题描述】: checkerThread = new Thread(new ThreadStart(() => CheckTokens()));
checkerThread.Start();
// Re-enable controls when done
stopCheckButton.Visible = false;
stopCheckButton.Enabled = false;
startCheckButton.Enabled = true;
loadTokenListButton.Enabled = true;
exportTokensButton.Enabled = true;
clearCheckButton.Enabled = true;
clearValidButton.Enabled = true;
tokenInputBox.Enabled = true;
当线程运行时,我的表单中的控件被禁用。我想在线程完成后重新启用它们。在不被thread.Join()
阻塞用户界面的情况下,我该怎么做?
【问题讨论】:
你听说过异步/等待吗? 使用 async / await 取决于 imo 必须完成的工作类型。 BackgroundWorker 在工具箱中,您会喜欢它的 RunWorkerCompleted 事件。 记住 - “await” 可能像病毒:它可以用愚蠢的“Async”声明“感染”代码库中不相关的部分。 @paulsm4 不,它只会影响代码库的相关部分,即任何关心异步操作完成时执行操作的部分。而且这个问题并不特定于async
作为关键字,它是异步操作所固有的,即使您使用其他形式的异步,也必须不阻塞 UI。
【参考方案1】:
我建议考虑使用BackgroundWorker
示例代码:
https://docs.microsoft.com/en-us/dotnet/desktop/winforms/controls/how-to-run-an-operation-in-the-background?view=netframeworkdesktop-4.8
这是另一个例子:
https://www.dotnetperls.com/backgroundworker-vbnet
public Class Form1 Public Class ArgumentType Public _a As Int32 Public _b As Int32 End Class Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load ' Create the argument object. Dim args As ArgumentType = New ArgumentType() args._a = 5 args._b = 6 ' Start up the BackgroundWorker1. ' ... Pass argument object to it. BackgroundWorker1.RunWorkerAsync(args) End Sub Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, _ ByVal e As System.ComponentModel.DoWorkEventArgs) _ Handles BackgroundWorker1.DoWork ' Do some time-consuming work on this thread. System.Threading.Thread.Sleep(1000) ' Get argument. Dim args As ArgumentType = e.Argument ' Return value based on the argument. e.Result = args._a * args._b End Sub Private Sub BackgroundWorker1_RunWorkerCompleted(ByVal sender As System.Object, _ ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) _ Handles BackgroundWorker1.RunWorkerCompleted ' Called when the BackgroundWorker is completed. MessageBox.Show(e.Result.ToString()) End Sub End Class
【讨论】:
@Janic - 正如 Frederik Gheysels 所说,“使用 async / await 取决于 imo 必须完成的工作类型”。我认为 BackgroudWorker 可能更适合您的需求。问:您在标题中说“C#”……但在标签中说 VB.Net。它是哪一个?这两个例子都应该很容易翻译成任何一种语言:) @Janic 如果您要学习一些东西,请不要学习过时的后台工作者。学习异步/等待。 @paulsm4await
是比 BGW 更更的通用工具。 await
可以做 BGW 可以做的一切,BGW 不能做 await
可以做的一切。如果这是一个BGW 根本不适合的问题,你只能用await
解决问题,而不是等待对Task.Run
的一次调用。
@Janic - 我相信“更新”不一定是“更好”。 BackgroundWorker 在这里非常合适。并且“等待”可以像病毒一样:它可以用其他不必要的“异步”声明“感染”代码库中不相关的部分。如果有帮助,请考虑“支持”和/或“接受”此回复。以上是关于C#等待线程完成而不阻塞UI [重复]的主要内容,如果未能解决你的问题,请参考以下文章
java 多次new DataOutputStream而不关闭,线程阻塞