VB.NET 中带有后台工作者的字幕进度条

Posted

技术标签:

【中文标题】VB.NET 中带有后台工作者的字幕进度条【英文标题】:Marquee Progress Bar with Background Worker in VB.NET 【发布时间】:2015-02-20 10:06:27 【问题描述】:

我有一个主窗体,底部状态条有一个进度条。它设置为选取框样式。我希望它在何时保持动画 我运行一个很长的函数。但是当函数命中时,表单和它上面的所有东西都会冻结,所以我使用了一个后台工作程序 运行长功能。但这在 MyClass.BigFunction() 代码中给了我以下错误。

跨线程操作无效:控件“frmMainNew”从创建它的线程以外的线程访问。

“frmMainNew”是progressbar和backgroundworker所在的主窗体。我将表单作为参数传递给 MyClass 对象 当我初始化它时。

这是我第一次使用backgroundworker,我还需要什么? 我已经查看了这些示例并尝试了它们,但没有任何效果。 (1、2、3、4、5、6)。

我也必须将它用于其他功能。

我的代码:

   Private WithEvents bgw As BackgroundWorker

Private Sub frmMainNew_Load(ByVal sender As Object, ByVal e As System.EventArgs) 处理 Me.Load

    Try
        Me.SuspendLayout()

    'Other Functions

        w_AddBackgroundWorkerForProgressBar()

        Me.ResumeLayout()

    Catch ex As Exception
        Scube.Planner.ErrorHandler.DisplayError(ex)
    End Try

End Sub

Private Sub w_AddBackgroundWorkerForProgressBar()
    bgw = New BackgroundWorker
    AddHandler bgw.DoWork, AddressOf bgw_DoWork
    AddHandler bgw.RunWorkerCompleted, AddressOf bgw_Completed
    'AddHandler bgw.ProgressChanged, AddressOf bgw_ProgressChanged
End Sub

Private Sub MyButton_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyButton.Click
    Try

        bgw.WorkerSupportsCancellation = True
        bgw.RunWorkerAsync()
        'MyClass.BigFunction()   <--- Originally called from here
    Catch ex As Exception
        Scube.Planner.ErrorHandler.DisplayError(ex)
    Finally
        Me.Cursor = Cursors.Default
    End Try
End Sub

Private Sub bgw_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs) Handles bgw.DoWork
    'Do your lenghty operations here

    MyClass.BigFunction()

    System.Threading.Thread.Sleep(10000)

End Sub

Private Sub bgw_Completed(ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs) Handles bgw.RunWorkerCompleted
    If Not IsNothing(e.Error) Then
        MessageBoxEx.Show(e.Error.ToString)
    End If
    ProgressBar1.Hide()
End Sub

Private Sub w_ShowProgressBar()
    ProgressBar1.Show()
    Me.Refresh()
    System.Windows.Forms.Application.DoEvents()
End Sub

【问题讨论】:

您必须从主窗体或其控件之一调用w_ShowProgressBar()。如果它由 BackgroundWorker 或 BigFunction() 调用,它将不起作用,因为 BackgroundWorker 执行的任何操作都将在不同的线程上执行,这意味着主窗体中的任何控件都不能从该线程修改。所以我建议你改为在按钮点击事件上调用进度条函数。 【参考方案1】:

您不能也不应该从您的“BigFunction()”访问您的 frmMainNew。它在一个单独的线程上工作,并且无权访问 UI 线程。我们需要看看你在你的 bigfunction 中做了什么来告诉你问题。我会猜测并说您正在尝试从该函数中更新进度条值?如果是这样,那么这样做的方法不正确。

您需要做的是,像这样在 BigFunction 中设置进度:

bgw.ReportProgress(Progress/Percentage)

并更改进度事件,在该事件内部是您更新进度条的地方。

Private Sub BackgroundWorker1_ProgressChanged(sender As Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
  Progressbar1.value = e.ProgressPercentage
End Sub

【讨论】:

我认为我们不需要再看到任何东西了。它必须是进度条,因为在上面的任何代码中都没有调用它。 w_ShowProgressBar() 调用移出 BigFunction 并移至 MyButton_Click() :) BigFunction 没有任何进度条或任何其他 UI 相关代码。这只是一个极其复杂的计算函数。我们正在添加一个进度条,因为它花费的时间太长并且屏幕在执行时会冻结。我会尝试这些建议。 你能解释一下这句话的意思吗--> “我在初始化时将表单作为参数传递给 MyClass 对象。” - 你的班级如何与表格互动?一旦 BigFunction 完成处理,结果会去哪里?您是否在 BigFunction 的类中使用其他对象/参数?您的 BigFunction 中是否还有代码来指示正在取得的进展? 该计算包含大量代码,涉及来自三种不同表单的大量信息以及主表单上的一些控件。因此,它有自己的类,我将 MainForm 作为参数传递给它的构造函数。但我明白你的意思。我在 MainForm 中编写了 ProgressChanged 事件。除非我这样做,否则如何从 MyClass 访问 bgw:ParentForm.bgw.ReportProgress(int)? 首先尝试找出为什么会弹出该错误。如有必要,逐行注释掉 myclass 中访问表单上任何元素的任何代码,然后从那里开始。

以上是关于VB.NET 中带有后台工作者的字幕进度条的主要内容,如果未能解决你的问题,请参考以下文章

关于VB.NET中进度条使用问题

关于VB.NET进度条的实例

从“My.resources”VB.net 复制文件的进度条

终端中带有块字符的文本进度条[关闭]

实现自定义背景色前景色显示进度的进度条

VB.NET显示程序的进度,该怎么做?