Пользовательский интерфейс не обновляется быстро

#wpf #vb.net #multithreading #silverlight #user-interface

#wpf #vb.net #многопоточность #silverlight #пользовательский интерфейс

Вопрос:

Добрый вечер,

Ниже приведен код, который я использовал для чтения файлов и папок с диска и т.д.

 Public Class LoadingBox

    Public counter As ULong
    Public OpenRecords As New Dictionary(Of String, MainWindow.records)
    Public Path As String
    Public Diskname As String
    Private WithEvents BKWorker As New BackgroundWorker()


    Public Sub New(ByVal _Path As String, ByVal _Diskname As String)

        ' This call is required by the designer.
        InitializeComponent()

        ' Add any initialization after the InitializeComponent() call.
        Path = _path
        Diskname = _diskname
    End Sub

    Private Sub GetStructure(ByVal tempdir As String, ByVal ParentID As String, ByVal DiskName As String)
        Dim maindir As DirectoryInfo = My.Computer.FileSystem.GetDirectoryInfo(tempdir)
        For Each Dir As DirectoryInfo In maindir.GetDirectories
            Try
                Dim d As New MainWindow.records
                d.Filename = Dir.Name
                d.Folder = True
                d.Rowid = Date.UtcNow.ToString()   counter.ToString()
                d.Size = 0
                d.ParentID = ParentID
                d.DiskName = DiskName
                d.DateCreated = Dir.CreationTimeUtc
                d.DateModified = Dir.LastWriteTimeUtc
                OpenRecords.Add(d.Rowid, d)
                'Label1.Content = "Processing: "   Dir.FullName
                BKWorker.ReportProgress(0, Dir.FullName)
                counter = counter   1
                GetStructure(Dir.FullName, d.Rowid, DiskName)
            Catch ex As Exception

            End Try


        Next
        For Each fil As FileInfo In maindir.GetFiles
            Try
                Dim d As New MainWindow.records
                d.Filename = fil.Name
                d.Folder = False
                d.Rowid = Date.UtcNow.ToString()   counter.ToString()
                d.Size = fil.Length
                d.ParentID = ParentID
                d.DiskName = DiskName
                d.DateCreated = fil.CreationTimeUtc
                d.DateModified = fil.LastWriteTimeUtc
                OpenRecords.Add(d.Rowid, d)
                'Label1.Content = "Processing: "   fil.FullName
                BKWorker.ReportProgress(0, fil.FullName)
                counter = counter   1
            Catch ex As Exception

            End Try

        Next
    End Sub

    Private Sub Window_Loaded(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded
        counter = 0
        BKWorker.WorkerReportsProgress = True
        AddHandler BKWorker.DoWork, AddressOf BKWorker_Do
        AddHandler BKWorker.ProgressChanged, AddressOf BKWorker_Progress
        AddHandler BKWorker.RunWorkerCompleted, AddressOf BKWorker_Completed
        BKWorker.RunWorkerAsync()

        'GetStructure(Path, "0", Diskname)
    End Sub

    Private Sub BKWorker_Do(ByVal sender As Object, ByVal e As DoWorkEventArgs)
        'Throw New NotImplementedException
        GetStructure(Path, "0", Diskname)
    End Sub

    Private Sub BKWorker_Progress(ByVal sender As Object, ByVal e As ProgressChangedEventArgs)
        'Throw New NotImplementedException
        Label1.Content = "Processing: "   e.UserState.ToString()
        If ProgressBar1.Value = 100 Then
            ProgressBar1.Value = 0
        End If
        ProgressBar1.Value = ProgressBar1.Value   1
    End Sub

    Private Sub BKWorker_Completed(ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs)
        'Throw New NotImplementedException
        MessageBox.Show("Completed")
        Me.Close()
    End Sub
End Class
  

Однако проблема в том, что фоновый поток способен читать файлы очень быстро, но поток пользовательского интерфейса не в состоянии поддерживать скорость с ним, не могли бы вы, пожалуйста, посоветовать мне, как я могу решить эту проблему.

Ответ №1:

Вам почти никогда не захочется сообщать о прогрессе по каждому отдельному элементу, когда вы перебираете такое количество элементов.

Я бы посоветовал найти некоторое разумное количество файлов, чтобы подождать, прежде чем сообщать о прогрессе. Каждый 5-й или каждый 10-й или так далее. Вероятно, вы захотите взглянуть на то, каково ваше обычное количество файлов. Другими словами, если вы обычно обрабатываете только 25 файлов, вы, вероятно, не хотите обновлять только каждые 10 файлов. Но если вы обычно обрабатываете 25000 файлов, вы могли бы, возможно, даже обновлять только каждые 100 файлов.

Комментарии:

1. Большое вам спасибо за быстрый ответ. Решаемая путем следования вашим советам.

Ответ №2:

Одним из быстрых ответов было бы сообщать о прогрессе только по истечении определенного количества времени, таким образом, если за это время было обработано 10 файлов, пользовательский интерфейс не пытается обновлять по одному каждый. Если все обрабатывается так быстро, то вам действительно не нужно обновлять пользователя для каждого отдельного файла.

Также на заметку, если ваша панель выполнения на самом деле не сообщает о прогрессе от 0 до 100%, вы можете просто установить для ее IsIndeterminate свойства значение true вместо увеличения процента и последующего сброса его обратно на 0.

Комментарии:

1. Большое вам спасибо за быстрый ответ. Решаемая путем следования вашим советам, а также отметил IsIndeterminate, спасибо за информативность.