首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >VB.NET进度条后台工作人员

VB.NET进度条后台工作人员
EN

Stack Overflow用户
提问于 2012-11-03 15:11:26
回答 6查看 30.2K关注 0票数 9

当我的应用程序启动时,并且它刚刚升级,我正在执行本地数据库更新(sqlite)。

它是这样的:用户启动我的应用程序,然后我开始升级过程。在这个升级过程中,我显示了一个具有连续进度条的表单。此表单在升级过程完成后关闭,然后用户可以开始使用我的应用程序。

但是进度条不会有动画效果,因为升级过程太密集了。

在我的旧VB6版本中,我使用了一个有1个表单并显示进度条的ActiveX-Exe。这是我的“后台工作人员”。

我不确定是否可以在VB.NET中使用相同的方法。

我只看到过在后台工作者中执行工作的示例,但我没有看到进度条本身是后台工作者的任何示例。

数据库升级需要阻止,在数据库升级完成之前,用户可能不会使用我的应用程序。这意味着只有进度栏应该“进程外”,而不是升级。

非常感谢!

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2012-11-21 13:05:22

先读一下这个:Use of Application.DoEvents()

因此,在读完上面的答案后,你将永远不会再使用DoEvents,而且如果没有DoEvents (和/或使ProgressBar无效,以便它的Paint事件将被激发),“进度条将不会激活,因为升级过程非常密集”。

因此Cthulhu的评论是--“你可以用进度条创建一个对话框,使该对话成为模态对话,然后在后台工作人员上执行你的数据库工具。”是最好的前进方式之一。

我已经翻译了一个我使用的C#实现,你应该可以直接把它放进去。

这是ProgressBar表单:

代码语言:javascript
复制
Public Partial Class ThinkingProgressBar
    Inherits Form
    Private startTime As System.DateTime = DateTime.Now
    Public Sub New()
        InitializeComponent()
    End Sub

    Private Sub lblClose_LinkClicked(sender As Object, e As LinkLabelLinkClickedEventArgs)
        Me.Tag = "Cancelled"
        Me.Hide()
    End Sub

    Public Sub SetThinkingBar(ByVal switchedOn As Boolean)
        If switchedOn Then
            lblTime.Text = "0:00:00"
            startTime = DateTime.Now
            Timer1.Enabled = True
            Timer1.Start()
        Else
            Timer1.Enabled = False
            Timer1.Stop()
        End If
    End Sub

    Private Sub timer1_Tick(sender As Object, e As EventArgs)
        Dim diff As New TimeSpan()
        diff = DateTime.Now.Subtract(startTime)
        lblTime.Text = diff.Hours & ":" & diff.Minutes.ToString("00") & ":" & diff.Seconds.ToString("00")
        lblTime.Invalidate()
    End Sub
End Class

将一个BackgroundWorker控件拖放到窗体上,下面是后台工作事件:

代码语言:javascript
复制
Private Sub backgroundWorker1_DoWork(sender As Object, e As DoWorkEventArgs) Handles BackgroundWorker1.DoWork
    e.Result = e.Argument
    'DirectCast(e.Result, ThinkingProgressBar).SetThinkingBar(True) 
    'DO LONG OPERATION HERE
    
End Sub

Private Sub backgroundWorker1_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
    Dim dlg As ThinkingProgressBar = TryCast(e.Result, ThinkingProgressBar)
    If IsNothing(dlg) = False Then
        dlg.SetThinkingBar(False)
        dlg.Close()
    End If
End Sub

下面是应用程序启动和升级时的调用代码:

代码语言:javascript
复制
Dim dlg As New ThinkingProgressBar()
dlg.SetThinkingBar(True)
BackgroundWorker1.RunWorkerAsync(dlg)
dlg.ShowDialog()
If IsNothing(dlg.Tag) = False AndAlso dlg.Tag.ToString() = "Cancelled" Then
    Return
End If

有几件事,你可以防止用户取消(即lblClose_LinkClicked),并设置保护/防御编程,以处理用户在升级过程中杀死进程或关闭PC的情况。

ProgressBar实际上是一个动画gif -这将适合您的使用,因为很难预测更新数据库所需的时间:

票数 12
EN

Stack Overflow用户

发布于 2012-11-15 15:06:58

在我看来,从你的要求来看,你正在寻找:

代码语言:javascript
复制
Application.DoAction()

我在一个应用程序中经历过,需要从xml加载2000到3000项相关细节,而实现的过程是一个接一个地读取项,这会挂起该过程。在循环中使用上面的代码行解决了我的问题。UI未挂起,用户可以在其他表单上工作。这对我来说似乎是progressbar is now as background process (在某种程度上)。

希望它能帮上忙!

票数 3
EN

Stack Overflow用户

发布于 2012-11-20 08:06:14

我理解您希望将进度栏作为后台线程的愿望,但我相当确定您无法做到这一点。因为您想要更新应用程序的可视组件,所以UI需要是主线程。禁用窗体上的所有控件非常容易,包括菜单项。

让我建议这个过程:

  1. 使用提到的进度栏显示窗体。
  2. 如果显示任何其他窗体,请禁用窗体上直接显示的所有子控件。根据控件的不同,您可能需要遍历它的子控件以禁用它们。
  3. 在执行数据库更新的代码中,将进度栏的值更新为所需的值。在更新值时,调用进度条的刷新方法。这将强制进度条绘制correctly.
  4. Once您的更新完成,隐藏进度条,重新启用您禁用的所有窗体上的所有控件。

这将给你一个在后台线程中运行的进度条的外观,同时仍然给你的应用程序提供所需的主线程阻塞。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13206926

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档