Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/vb.net/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Wpf BackgroundWorker.ReportProgress不';在我的UI中不显示更改_Wpf_Vb.net_Multithreading_Backgroundworker - Fatal编程技术网

Wpf BackgroundWorker.ReportProgress不';在我的UI中不显示更改

Wpf BackgroundWorker.ReportProgress不';在我的UI中不显示更改,wpf,vb.net,multithreading,backgroundworker,Wpf,Vb.net,Multithreading,Backgroundworker,我有一个比较按钮,可以启动后台工作程序 Private Sub btnCompare_Click(sender As Object, e As EventArgs) Handles btnCompare.Click m_ProgressBar = New ProgressBar m_ProgressBar.Show() m_ProgressBar.txtBlockMainProgress.Dispatcher.BeginInvoke(Sub()

我有一个比较按钮,可以启动后台工作程序

Private Sub btnCompare_Click(sender As Object, e As EventArgs) Handles btnCompare.Click

    m_ProgressBar = New ProgressBar
    m_ProgressBar.Show()
    m_ProgressBar.txtBlockMainProgress.Dispatcher.BeginInvoke(Sub()
                                                                  m_ProgressBar.txtBlockMainProgress.Text = "Comparing excel file(s)... Please wait. This might take a while."
                                                              End Sub)

    Me.backgroundWorker = New BackgroundWorker
    Me.backgroundWorker.WorkerReportsProgress = True
    Me.backgroundWorker.WorkerSupportsCancellation = True
    AddHandler Me.backgroundWorker.DoWork, AddressOf worker_DoWork
    AddHandler Me.backgroundWorker.ProgressChanged, AddressOf worker_ProgressChanged
    AddHandler Me.backgroundWorker.RunWorkerCompleted, AddressOf worker_RunWorkerCompleted
    Me.backgroundWorker.RunWorkerAsync()
    TaskbarItemInfo.ProgressState = Shell.TaskbarItemProgressState.Normal

End Sub
我的backgroundworker的DoWork事件初始化一个类比较,该类比较具有一个名为Compare的方法,该方法接受backgroundworker作为参数

    Private Sub worker_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs)

    blnCompareDone = True

    objExcelCompare = New Compare

    With objExcelCompare
        .SetThreshold = dblThreshold
        .CompareToBestMatchData = blnBestMatchFlg

        .CompareMerge = blnCompareMerge
        .CompareTextWrap = blnCompareTextWrap
        .CompareTextAlign = blnCompareTextAlign
        .CompareOrientation = blnCompareOrientation
        .CompareBorder = blnCompareBorder
        .CompareBackColor = blnCompareBackColor
        .CompareFont = blnCompareFont

        .NoOfPages = intNoOfPages
        .Page_Location_1 = objLocation_1
        .Page_Location_2 = objLocation_2
        .RemovedColumn = objRemoveCol
        .RemovedRow = objRemoveRow
        .AddedColumn = objAddCol
        .AddedRow = objAddRow
        .DataChange = objChangeData

        .Compare(objWorksheet_1, objWorksheet_2, Me.backgroundWorker, e)

        objEquivalentColumns = .EquivalentColumns
        objEquivalentRows = .EquivalentRows
        objValueResult_1 = .ValueResult_1
        objValueResult_2 = .ValueResult_2
        objFormatResult = .FormatResult
    End With

End Sub
在比较方法中,我使用ReportProgress在比较excel文件的每一页后更新UI。总共有2页,因此进度条的更新将是50%,然后是100%

    Public Sub Compare(ByRef p_objWorkSheet_1 As Worksheet, ByRef p_objWorkSheet_2 As Worksheet, ByRef p_backgroundWorker As BackgroundWorker, ByRef e As System.ComponentModel.DoWorkEventArgs)

    If p_objWorkSheet_1 Is Nothing OrElse p_objWorkSheet_2 Is Nothing Then
        'Error when no instance on either worksheets was found
        Throw New Exception("No instances of worksheet is found.")
        Exit Sub
    End If

    '********************Start of Comparison*********************
    objExcelData_1 = New Dictionary(Of Integer, Dictionary(Of Tuple(Of Integer, Integer), Range))
    objExcelData_2 = New Dictionary(Of Integer, Dictionary(Of Tuple(Of Integer, Integer), Range))

    objEquivalentColumns = New Dictionary(Of Integer, Dictionary(Of Integer, Integer))
    objEquivalentRows = New Dictionary(Of Integer, Dictionary(Of Integer, Integer))

    objValueResult_1 = New Dictionary(Of Integer, Dictionary(Of Tuple(Of Integer, Integer), List(Of ValueError)))
    objValueResult_2 = New Dictionary(Of Integer, Dictionary(Of Tuple(Of Integer, Integer), List(Of ValueError)))
    objFormatResult = New Dictionary(Of Integer, Dictionary(Of Tuple(Of Integer, Integer), List(Of FormatError)))

    'Loop through all pages
    For w_intCtr_1 As Integer = 1 To intNoOfPages

        If p_backgroundWorker.CancellationPending = True Then
            e.Cancel = True
            Return
        End If

        Dim w_intCurrentStep As Integer = 1
        GetExcelData(p_objWorkSheet_1, objExcelData_1, objLocation_1, w_intCtr_1)
        GetExcelData(p_objWorkSheet_2, objExcelData_2, objLocation_2, w_intCtr_1)

        If objExcelData_1 Is Nothing OrElse objExcelData_2 Is Nothing Then
            'No data to compare
            Exit Sub
        End If

        objCompareByData = New Compare_Data

        'Compare value of excelsheets
        With objCompareByData
            'Set threshold, excel data, and location of page to compare
            .SetThreshold = dblThreshold
            .CompareToBestMatchData = blnBestMatchFlg

            .SetExcelData_1 = objExcelData_1(w_intCtr_1)
            .SetLocation_1 = objLocation_1(w_intCtr_1)

            .SetExcelData_2 = objExcelData_2(w_intCtr_1)
            .SetLocation_2 = objLocation_2(w_intCtr_1)

            If objRemoveCol Is Nothing = False AndAlso objRemoveCol.ContainsKey(w_intCtr_1) Then
                .SetRemovedColumn = objRemoveCol(w_intCtr_1)
            End If
            If objRemoveRow Is Nothing = False AndAlso objRemoveRow.ContainsKey(w_intCtr_1) Then
                .SetRemovedRow = objRemoveRow(w_intCtr_1)
            End If
            If objAddCol Is Nothing = False AndAlso objAddCol.ContainsKey(w_intCtr_1) Then
                .SetAddedColumn = objAddCol(w_intCtr_1)
            End If
            If objAddRow Is Nothing = False AndAlso objAddRow.ContainsKey(w_intCtr_1) Then
                .SetAddedRow = objAddRow(w_intCtr_1)
            End If

            If objChangeData Is Nothing = False AndAlso objChangeData.ContainsKey(w_intCtr_1) Then
                .SetDataChange = objChangeData(w_intCtr_1)
            End If

            If p_backgroundWorker.CancellationPending = True Then
                e.Cancel = True
                Return
            End If

            'Proceed to compare
            .Compare()

            objEquivalentColumns.Add(w_intCtr_1, .EquivalentColumns)
            objEquivalentRows.Add(w_intCtr_1, .EquivalentRows)

            objValueResult_1.Add(w_intCtr_1, .ExcelData_Result_1)
            objValueResult_2.Add(w_intCtr_1, .ExcelData_Result_2)
        End With

        If blnCompareMerge OrElse blnCompareTextWrap OrElse blnCompareTextAlign OrElse blnCompareOrientation OrElse blnCompareBorder OrElse blnCompareBackColor OrElse blnCompareFont Then
            objCompareByFormat = New Compare_Format

            'Compare format of excelsheets
            With objCompareByFormat
                'Set excel data to compare
                .SetExcelFormat_1 = objExcelData_1(w_intCtr_1)
                .SetExcelFormat_2 = objExcelData_2(w_intCtr_1)
                'Set equivalent columns of page retrieved from comparing values of both excel sheets
                'Set equivalent rows of page retrieved from comparing values of both excel sheets
                If objEquivalentColumns Is Nothing = False AndAlso objEquivalentColumns.ContainsKey(w_intCtr_1) Then
                    .SetEquivalentColumns = objEquivalentColumns(w_intCtr_1)
                End If
                If objEquivalentRows Is Nothing = False AndAlso objEquivalentRows.ContainsKey(w_intCtr_1) Then
                    .SetEquivalentRows = objEquivalentRows(w_intCtr_1)
                End If

                .CompareMerge = blnCompareMerge
                .CompareTextWrap = blnCompareTextWrap
                .CompareTextAlign = blnCompareTextAlign
                .CompareOrientation = blnCompareOrientation
                .CompareBorder = blnCompareBorder
                .CompareBackColor = blnCompareBackColor
                .CompareFont = blnCompareFont

                If p_backgroundWorker.CancellationPending = True Then
                    e.Cancel = True
                    Return
                End If

                .Compare()

                'Set comparison result of page to collection
                objFormatResult.Add(w_intCtr_1, .ExcelFormat_Result)
            End With
        End If

        If p_backgroundWorker.CancellationPending = True Then
            e.Cancel = True
            Return
        End If

        'Set result to excel sheets
        AddValueResultToWorkSheet(p_objWorkSheet_1, p_objWorkSheet_2, w_intCtr_1)

        If p_backgroundWorker.CancellationPending = True Then
            e.Cancel = True
            Return
        End If

        'Set result to excel sheets
        AddFormatResultToWorkSheet(p_objWorkSheet_2, w_intCtr_1)

        p_backgroundWorker.ReportProgress((100 / intNoOfPages) * w_intCtr_1, (100 / intNoOfPages) * w_intCtr_1 & "% Completed " & w_intCtr_1 & " out of " & intNoOfPages & " pages")
        Thread.Sleep(3000)
    Next
End Sub
如果我在每次进度报告后都放上Thread.Sleep(3000),效果会很好。这是我的ProgressChanged事件处理程序

Private Sub worker_ProgressChanged(sender As Object, e As ProgressChangedEventArgs)

    m_ProgressBar.pbStatusMain.Dispatcher.BeginInvoke(Sub()
                                                          m_ProgressBar.pbStatusMain.IsIndeterminate = False
                                                          m_ProgressBar.pbStatusMain.Value = e.ProgressPercentage
                                                      End Sub)

    m_ProgressBar.txtBlockMainProgress.Dispatcher.BeginInvoke(Sub()
                                                                  m_ProgressBar.txtBlockMainProgress.Text = e.UserState
                                                              End Sub)

    TaskbarItemInfo.ProgressValue = e.ProgressPercentage / 100

End Sub

我想知道为什么有时有效,有时无效。根据我的研究,UI线程被大量的消息淹没,导致它没有响应,或者我使用ReportProgress频繁,导致UI线程忽略下一个请求。我做错了什么?为什么更改不适用于我的UI?

为什么要在
ProgressChanged
事件处理程序中进行这些
BeginInvoke
调用?关键是在UI线程上引发了
ProgressChanged
,因此直接修改UI是安全的。摆脱这些,看看情况是否正常。如果没有,请尝试在您修改的控件上调用
Refresh
。我尝试了BeginInvoke、Invoke、Dispatcher,但都会产生相同的结果。我该如何刷新?事实上,我写这篇文章时正在考虑WinForms。我不确定WPF中的等价物是什么,或者是否有。从未尝试过。要明确的是,如果你摆脱了那些“BeginInvoke”呼叫,只保留lambdas的内容,问题仍然存在,对吗?我想这就是你最初的想法。是的。我还尝试了application.do事件,但仍然没有更新UI。我已经花了好几个星期在这上面了。有时thread.sleep()不起作用。当然,在UI线程上运行太多代码会导致此问题。不仅仅是ReportProgress()和BeginInvoke()调用负责,它还在工作线程中使用Excel对象模型。这是一个COM对象模型,您使用的任何方法和属性实际上都在UI线程上执行。COM管道使用相当于Dispatcher.Invoke()的函数来确保代码线程安全。取得进展的唯一真正方法是在STA线程上创建应用程序接口,这样就不需要封送处理。