vb.net - 如何在 VB.NET 表单中处理长时间运行的任务?
问题描述
我目前正在开发一个 VB.NET 表单,该表单根据 Excel 文件和表单询问的一些额外数据(项目名称、客户名称、使用 SQL ......)自动创建 Word 文档。
此过程运行良好,大约需要 1 或 2 分钟才能完成。问题是我所有的脚本都在ButtonGenerate.Click
Handler 中。因此,当按下“生成”按钮时,表单窗口会变砖,无法取消...
它不应该在 Click 处理程序中。为那个长任务打开一个新线程似乎更好。但是多线程对我来说不是很熟悉。我尝试使用启动脚本
ThreadPool.QueueUserWorkItem(...
但是我的 Generate Sub 设置标签并在主窗体中更新进度条,所以除非我使用,否则我不会工作
Me.Invoke(New MethodInvoker(Sub()
label.Text = "..."
ProgressBar.Value = 10
' ...
End Sub)
每次我需要更新表单上的某些内容时,我什至无法使用该按钮检索任何新的按钮(取消按钮会很好)。
这基本上是我的代码:
Public Class TestFichesAutomation
Private Sub BtnGenerate_Click(sender As Object, e As EventArgs) Handles BtnGenerate.Click
System.Threading.ThreadPool.QueueUserWorkItem(Sub() Generate())
End Sub
Public Sub Generate()
' Check user options, retrieve Excel Data, SQL, Fill in custom classes, create Word docs (~ 1 minute)
End Sub
那么您将如何处理该脚本?线程甚至是一个好的解决方案吗?
解决方案
非常感谢您的帮助^^和有用的文档。
我的应用程序现在打开一个新线程并使用 2 个自定义类来充当缓冲区:
Private Async Sub Btn_Click(sender As Object, e As EventArgs) Handles Btn.Click
myProgress = New Progress
' a custom class just for the UI with the current task, current SQL connection status and progress value in %
_Options.ProjectName = TextBoxProjectName.Text
_Options.CustomerName = TextBoxCustomerName.Text
...
' Fill in a custom "_Options" private class to act as a buffer between the 2 thread (the user choices)
Loading = New Loading()
Me.Visible = False
Loading.Show() ' Show the Loading window (a ProgressBar and a label : inputLine)
Task.Run(Function() Generate(Progress, _Options))
Me.Visible = True
End Sub
Public Async Function Generate(ByVal myProgress As Progress, ByVal Options As Options) As Task(Of Boolean)
' DO THE LONG JOB and sometimes update the UI :
myProgress.LoadingValue = 50 ' %
myProgress.CurrentTask= "SQL query : " & ...
Me.Invoke(New MethodInvoker(Sub() UpdateLoading()))
' Check if the task has been cancelled ("Cancelled" is changed by a passvalue from the Loading window):
If myProgress.Cancelled = True Then ...
' Continue ...
End Function
Public Shared Sub UpdateLoading()
MyForm.Loading.ProgressBar.Value = myProgress.LoadingValue
MyForm.Loading.inputLine.Text = myProgress.CurrentTask
' ...
End Sub
推荐阅读
- reactjs - 安装后容器显示不正确
- laravel - 是否可以在 laravel 验证规则中验证数字键?
- java - \\W? 在 Java 正则表达式中
- php - 仅允许某些用户帐户进入页面
- python - 如何消除除一个特定变量/列之外的所有具有特定列名的列?
- c# - 某些服务无法构建(验证服务描述符时出错'...IHostedService
- postgresql - 了解 macOS 上的 LANG
- c# - 如何比较具有相同键但不同值的两个字典值?
- wpf - 将 image.source 转换为位图
- google-bigquery - 如何在 Google Big Query 中创建动态更改数据集的查询?