【问题标题】:VB.Net Asynchronous background worker inside a loop循环内的VB.Net异步后台工作者
【发布时间】:2010-07-08 11:01:30
【问题描述】:

我正在使用 Vb.net Visual Studio 2008。我有一个要在后台运行的进程(system.diagnostics.process),它更新了 Ui 线程进度条和一个标签,我使用 backgroundworker.runworkerAsync 进行了工作。现在的问题是我必须使用不同的输入多次处理相同的过程。

代码块是:

Private Sub fnStartEvent(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnStart.click

Dim inputFolder = Directory.GetFiles(textboxSourceFolder.text) 
Dim currentNumberOfFile As Integer=1
For each Files in inputFolder
   Dim arguments As Object = Files
   updateProgressStatus(0, currentNumberOfFile)
   BackgroundWorker1.WorkerReportsProgress = True
   BackgroundWorker1.RunWorkerAsync(New Object() {arguments})
  currentNumberOfFile += 1
  Next       
End Sub

  Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
  'uses the arguments
      Dim Bg_process As System.Diagnostics.Process = New System.Diagnostics.Process
            With Bg_process.StartInfo
                .Arguments = str_arguments
                .FileName = ffmpegPath
                .CreateNoWindow = True
                .UseShellExecute = False
                .RedirectStandardOutput = True
                .RedirectStandardError = True
            End With

            Bg_process.Start()
            Dim outputReader As StreamReader = Bg_process.StandardError
            Dim output As String

            While Not Bg_process.HasExited
                output = outputReader.ReadLine()
                BackgroundWorker1.ReportProgress(0, output)
                Threading.Thread.Sleep(500)
            End While
      End Sub

 Private Sub BackgroundWorker1_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
   ' process args

updateProgressStatus(args(0), args(1) )
End Sub

Private Function BackgroundWorker1_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs)  Handles BackgroundWorker1.RunWorkerCompleted
            Messagebox.Show(e.error.ToString)
End Try

  Sub updateProgressStatus(ByVal progressValue As Integer, ByVal progressStatus As String)
progressBar.value = progressValue
lblprogressStatus.Text = progressStatus
      End Sub

这里的问题是 fnStartEvent 方法一旦启动,它会调用 BackgroundWorker1.runWorkerAsync 进程并且在单独的线程中运行并且不等待线程完成并且它移动到下一行代码,即循环到下一项,它返回到相同的 BackgroundWorker1.runWorkerAsync 行并抛出它已经在运行的异常。

试过了 1.

    Private Sub fnStartEvent(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnStart.click
    Dim inputFolder = Directory.GetFiles(textboxSourceFolder.text) 
    Dim currentNumberOfFile As Integer=1
    For each Files in inputFolder

       Dim arguments As Object = Files
       updateProgressStatus(0, currentNumberOfFile)
       BackgroundWorker1.WorkerReportsProgress = True
       BackgroundWorker1.RunWorkerAsync(New Object() {arguments})
    ''
       Do Until BackgroundWorker1.IsBusy
       Thread.Sleep(500)
       Loop

  currentNumberOfFile += 1
  Next       
End Sub

但这不会更新用于表示进度的 Ui 线程。

2.将整个进程放在DoWork线程中,并在其中循环每个文件,但这会在进度条更新中返回跨线程错误。

执行一个循环以等待完成以及更新 UI 而不阻塞它的标准过程是什么。

【问题讨论】:

    标签: vb.net multithreading loops progress-bar backgroundworker


    【解决方案1】:

    每当您使用 Thread.Sleep 时,您实际上是在休眠与您的启动类(即 Form)挂钩的当前线程。因此,如果您休眠主线程,则不会发生 UI 更新。

    根据有关 BackgroundWorker.IsBusy 的 MSDN 文章,您需要抛出一个 Application.DoEvents。下面的代码是从上面链接的文章中复制的。

    
    Private Sub downloadButton_Click( _
        ByVal sender As Object, _
        ByVal e As EventArgs) _
        Handles downloadButton.Click
    
        ' Start the download operation in the background.
        Me.backgroundWorker1.RunWorkerAsync()
    
        ' Disable the button for the duration of the download.
        Me.downloadButton.Enabled = False
    
        ' Once you have started the background thread you 
        ' can exit the handler and the application will 
        ' wait until the RunWorkerCompleted event is raised.
    
        ' If you want to do something else in the main thread,
        ' such as update a progress bar, you can do so in a loop 
        ' while checking IsBusy to see if the background task is
        ' still running.
        While Me.backgroundWorker1.IsBusy
            progressBar1.Increment(1)
            ' Keep UI messages moving, so the form remains 
            ' responsive during the asynchronous operation.
            Application.DoEvents()
        End While
    End Sub
    

    【讨论】:

    • 感谢 josaph ,它的工作原理。但是是否有任何其他解决方案可以解决这个问题,bCoz 这里出现了许多线程循环。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-02-04
    • 1970-01-01
    • 2011-07-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-02
    相关资源
    最近更新 更多