BackgroundWorker UI不会更新Windows Phone 7中的进度

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BackgroundWorker UI不会更新Windows Phone 7中的进度相关的知识,希望对你有一定的参考价值。

在Windows Phone 7中,我试图显示一些LINQ查询的状态。我正在使用BackgroundWorker。我在Debug窗口中看到进度更新,但在UI(TextBlock4.Text)中没有。在所有查询结束后,似乎更新了进度。此外,UI在运行查询时没有响应。如何避免UI冻结?如何在UI中显示进度?还有另一种显示查询进度的方法吗?

Partial Public Class pagInvoicesReport
Inherits PhoneApplicationPage

Private WithEvents mWorker As New BackgroundWorker()

Private nJan As Nullable(Of Decimal) = 0
Private nFeb As Nullable(Of Decimal) = 0
Private nMar As Nullable(Of Decimal) = 0
Private nApr As Nullable(Of Decimal) = 0
Private nMay As Nullable(Of Decimal) = 0
Private nJun As Nullable(Of Decimal) = 0
Private nJul As Nullable(Of Decimal) = 0
Private nAug As Nullable(Of Decimal) = 0
Private nSept As Nullable(Of Decimal) = 0
Private nOct As Nullable(Of Decimal) = 0
Private nNov As Nullable(Of Decimal) = 0
Private nDec As Nullable(Of Decimal) = 0

Public Sub New()
    InitializeComponent()
    mWorker.WorkerReportsProgress = True
End Sub

Private Sub startButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles startButton.Click
    mWorker.RunWorkerAsync()
End Sub

Private Sub mWorker_ProgressChanged(ByVal sender As Object, ByVal e As ProgressChangedEventArgs) Handles mWorker_ProgressChanged
    TextBlock4.Text = e.ProgressPercentage.ToString() & "%"
    System.Diagnostics.Debug.WriteLine(e.ProgressPercentage.ToString() & "%")
End Sub

Private Sub GetGraphValues() Handles mWorker.DoWork
    System.Windows.Deployment.Current.Dispatcher.BeginInvoke( _
            Sub()
                Using theDB As New appContext("Data Source=isostore:/theDB.sdf")
                    Try
                        If (Aggregate r In theDB.InvoicesRecords Where r.InvoiceDateTime.Month = 1 And r.InvoiceDateTime.Year = 2012 And r.MainID = 1 Into Sum(CType(r.Cost, Decimal?))) IsNot Nothing Then
                            nJan = (Aggregate r In theDB.InvoicesRecords Where r.InvoiceDateTime.Month = 1 And r.InvoiceDateTime.Year = 2012 And r.MainID = 1 Into Sum(CType(r.Cost, Decimal?)))
                        Else
                            nJan = 0
                        End If
                    Catch ex As Exception
                        MessageBox.Show("There was an error!" & vbCrLf & ex.Message, "Error!", MessageBoxButton.OK)
                    End Try
                End Using
            End Sub)

    mWorker.ReportProgress(8)

    System.Windows.Deployment.Current.Dispatcher.BeginInvoke( _
        Sub()
            Using theDB As New appContext("Data Source=isostore:/theDB.sdf")
                Try
                    If (Aggregate r In theDB.InvoicesRecords Where r.InvoiceDateTime.Month = 2 And r.InvoiceDateTime.Year = 2012 And r.MainID = 1 Into Sum(CType(r.Cost, Decimal?))) IsNot Nothing Then
                        nFeb = (Aggregate r In theDB.InvoicesRecords Where r.InvoiceDateTime.Month = 2 And r.InvoiceDateTime.Year = 2012 And r.MainID = 1 Into Sum(CType(r.Cost, Decimal?)))
                    Else
                        nFeb = 0
                    End If
                Catch ex As Exception
                    MessageBox.Show("There was an error!" & vbCrLf & ex.Message, "Error!", MessageBoxButton.OK)
                End Try
            End Using
        End Sub)

    mWorker.ReportProgress(17)



    System.Windows.Deployment.Current.Dispatcher.BeginInvoke( _
        Sub()
            Using theDB As New appContext("Data Source=isostore:/theDB.sdf")
                Try
                    If (Aggregate r In theDB.InvoicesRecords Where r.InvoiceDateTime.Month = 12 And r.InvoiceDateTime.Year = 2012 And r.MainID = 1 Into Sum(CType(r.Cost, Decimal?))) IsNot Nothing Then
                        nDec = (Aggregate r In theDB.InvoicesRecords Where r.InvoiceDateTime.Month = 12 And r.InvoiceDateTime.Year = 2012 And r.MainID = 1 Into Sum(CType(r.Cost, Decimal?)))
                    Else
                        nDec = 0
                    End If
                Catch ex As Exception
                    MessageBox.Show("There was an error!" & vbCrLf & ex.Message, "Error!", MessageBoxButton.OK)
                End Try
            End Using
        End Sub)
    mWorker.ReportProgress(100)
End Sub

结束班

答案

看起来您正在发布要在UI线程上完成的工作。你的DoWork方法不应该调用Dispatcher。这将把所有工作放在UI线程而不是BackgroundWorker线程上。

更新:刚刚注意到您是访问成员变量。不推荐这样做,你的后台工作者应该返回它计算的结果,这是一个简单的例子,显示List中返回的结果(我不是VB专家,所以请耐心等待)。当工人完成时,取结果并替换您的属性

尝试将DoWork处理程序更改为:

Private Sub GetGraphValues(args as DoWorkEventArgs) Handles mWorker.DoWork
    Dim list as List<Decimal>();
    Dim jan as Decimal
    Dim feb as Decimal
    Dim dec as Dicimal
    Using theDB As New appContext("Data Source=isostore:/theDB.sdf")
        Try
            If (Aggregate r In theDB.InvoicesRecords Where r.InvoiceDateTime.Month = 1 And r.InvoiceDateTime.Year = 2012 And r.MainID = 1 Into Sum(CType(r.Cost, Decimal?))) IsNot Nothing Then
                jan = (Aggregate r In theDB.InvoicesRecords Where r.InvoiceDateTime.Month = 1 And r.InvoiceDateTime.Year = 2012 And r.MainID = 1 Into Sum(CType(r.Cost, Decimal?)))
            Else
                jan = 0
            End If
        Catch ex As Exception
            ' Showing messageBox SHOULD be shown on UI thread
            System.Windows.Deployment.Current.Dispatcher.BeginInvoke( _
            Sub()
                MessageBox.Show("There was an error!" & vbCrLf & ex.Message, "Error!", MessageBoxButton.OK)
            End Sub)
        End Try
    End Using
    list.Add(jan);

    mWorker.ReportProgress(8)

    Using theDB As New appContext("Data Source=isostore:/theDB.sdf")
        Try
            If (Aggregate r In theDB.InvoicesRecords Where r.InvoiceDateTime.Month = 2 And r.InvoiceDateTime.Year = 2012 And r.MainID = 1 Into Sum(CType(r.Cost, Decimal?))) IsNot Nothing Then
                feb = (Aggregate r In theDB.InvoicesRecords Where r.InvoiceDateTime.Month = 2 And r.InvoiceDateTime.Year = 2012 And r.MainID = 1 Into Sum(CType(r.Cost, Decimal?)))
            Else
                feb = 0
            End If
        Catch ex As Exception
            ' Showing messageBox SHOULD be shown on UI thread
            System.Windows.Deployment.Current.Dispatcher.BeginInvoke( _
            Sub()
                MessageBox.Show("There was an error!" & vbCrLf & ex.Message, "Error!", MessageBoxButton.OK)
            End Sub)
        End Try
    End Using
    list.Add(feb)

    mWorker.ReportProgress(17)

    Using theDB As New appContext("Data Source=isostore:/theDB.sdf")
        Try
            If (Aggregate r In theDB.InvoicesRecords Where r.InvoiceDateTime.Month = 12 And r.InvoiceDateTime.Year = 2012 And r.MainID = 1 Into Sum(CType(r.Cost, Decimal?))) IsNot Nothing Then
                dec = (Aggregate r In theDB.InvoicesRecords Where r.InvoiceDateTime.Month = 12 And r.InvoiceDateTime.Year = 2012 And r.MainID = 1 Into Sum(CType(r.Cost, Decimal?)))
            Else
                dec = 0
            End If
        Catch ex As Exception
            ' Showing messageBox SHOULD be shown on UI thread
            System.Windows.Deployment.Current.Dispatcher.BeginInvoke( _
            Sub()
                MessageBox.Show("There was an error!" & vbCrLf & ex.Message, "Error!", MessageBoxButton.OK)
            End Sub)
        End Try
    End Using
    list.Add(dec)

    mWorker.ReportProgress(100)
    args.Result = list
End Sub

以上是关于BackgroundWorker UI不会更新Windows Phone 7中的进度的主要内容,如果未能解决你的问题,请参考以下文章

BackgroundWorker:Argument-Object 的子代

自动滚动到由 backgroundworker 更新的多行文本框的底部

BackgroundWorker使用秒表更新经过的时间标签,由于调用C#而冻结[重复]

多个并行未定义的BackgroundWorker [重复]

为啥我只能从 BackgroundWorker 访问一些 UI 控件属性?

BackgroundWorker 使用 COM 对象导致 UI 线程挂起