Task.Factory.StartNew / Invoke / DGV updatet nicht

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 5 Antworten in diesem Thema. Der letzte Beitrag () ist von mrMo.

    Task.Factory.StartNew / Invoke / DGV updatet nicht

    Hallo!

    Ich habe eine Form mit einem DataGridView.
    Dieses hat ein DataBinding an einer DataTable.
    Nun starte ich das Befüllen der DataTable mit "Task.Factory.StartNew(AddressOf ScanDirectory)" wobei "ScanDirectory" eine "For Each" Schleife ausführt!

    Wenn ich die "For Each" Schleife ohne Task, also im GUI-Thread, laufen lasse werden nach jedem Schleifendurchlauf die neuen Einträge im DGV angezeigt bzw. aktualisiert!
    Da dies aber meine GUI einfrieren lässt habe ich des "Task.Factory.StartNew(AddressOf ScanDirectory)" vorangestellt.
    Aber dadurch wird das DGV nicht mehr aktualisiert..
    ..auch ein Invoken des DGV in der Schleife aktualisiert das DGV nicht!

    Was muss ich tun um in einem Task das DGV richtig zu invoken bzw. die Daten in Echtzeit aktualisieren zu sehen?
    OK, also ich hab jetzt nen Counter eingebaut der mir bei jedem hundertsten Eintrag des DGV refreshen soll!

    VB.NET-Quellcode

    1. If _pbCounter Mod 100 = 0 Then
    2. FileInfo_TableDataGridView.Invoke(Sub()
    3. FileInfo_TableDataGridView.Refresh()
    4. End Sub)
    5. End If


    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.IO
    2. Public Class Form1
    3. Private AllFiles_FileInfos As IEnumerable(Of IO.FileInfo)
    4. Public WithEvents AllFiles_DataTable As FileDataTable.FileInfo_TableDataTable = New FileDataTable.FileInfo_TableDataTable
    5. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    6. End Sub
    7. Private guiShown As Boolean = False
    8. Private Sub Form1_Shown(sender As Object, e As EventArgs) Handles MyBase.Shown
    9. Utils.DoubleBuffer_Controls.SetDoubleBuffered(FileInfo_TableDataGridView)
    10. 'FileInfoTableDataTableBindingSource.DataSource = AllFiles_DataTable
    11. FileInfo_TableDataGridView.DataSource = AllFiles_DataTable
    12. ' AddHandler AllFiles_DataTable.TableNewRow, AddressOf Table_NewRow
    13. guiShown = True
    14. End Sub
    15. Private fbd_ScanDirectory As New FolderBrowserDialog()
    16. Private thread_ScanDirectory As Threading.Thread
    17. Private Sub TestToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles TestToolStripMenuItem.Click
    18. If fbd_ScanDirectory.ShowDialog() = DialogResult.OK Then
    19. AllFiles_FileInfos = Utils.FileIterator.GetFileInfos(fbd_ScanDirectory.SelectedPath, "*.mp3")
    20. ToolStripProgressBar1.Value = 0
    21. ToolStripProgressBar1.Maximum = AllFiles_FileInfos.Count
    22. AllFiles_DataTable.Clear()
    23. 'Task.Factory.StartNew(AddressOf task_ScanDirectory)
    24. Task.Factory.StartNew(AddressOf ScanDirectory)
    25. 'ScanDirectory()
    26. End If
    27. End Sub
    28. Private _pbCounter As Integer = 0
    29. Private Sub task_ScanDirectory()
    30. thread_ScanDirectory = New Threading.Thread(New Threading.ThreadStart(AddressOf ScanDirectory))
    31. thread_ScanDirectory.Start()
    32. End Sub
    33. Public Sub ScanDirectory()
    34. Dim imgCon As New ImageConverter()
    35. 'File_DataTable.BeginLoadData()
    36. _pbCounter = 0
    37. For Each _fi As IO.FileInfo In AllFiles_FileInfos
    38. Dim _newRow As FileDataTable.FileInfo_TableRow = AllFiles_DataTable.NewFileInfo_TableRow()
    39. Try
    40. _newRow.Name = _fi.Name
    41. _newRow.Length = _fi.Length
    42. _newRow.Directory = _fi.DirectoryName
    43. _newRow.Created = _fi.CreationTimeUtc
    44. Dim _mp3File As Mp3Lib.Mp3File = New Mp3Lib.Mp3File(_fi)
    45. _newRow.Album = _mp3File.TagHandler.Album
    46. _newRow.Artist = _mp3File.TagHandler.Artist
    47. _newRow.Comment = _mp3File.TagHandler.Comment
    48. _newRow.Composer = _mp3File.TagHandler.Composer
    49. _newRow.Disc = _mp3File.TagHandler.Disc
    50. _newRow.FrameModel = _mp3File.TagHandler.FrameModel.ToString
    51. _newRow.Genre = _mp3File.TagHandler.Genre
    52. _newRow.Lenght = _mp3File.TagHandler.Length.ToString
    53. _newRow.Lyrics = _mp3File.TagHandler.Lyrics
    54. _newRow.PaddingSize = _mp3File.TagHandler.PaddingSize
    55. If IsNothing(_mp3File.TagHandler.Picture) = False Then
    56. _newRow.Picture = DirectCast(imgCon.ConvertTo(_mp3File.TagHandler.Picture, GetType(Byte())), Byte())
    57. Else
    58. _newRow.Picture = Nothing
    59. End If
    60. _newRow.Song = _mp3File.TagHandler.Song
    61. _newRow.Title = _mp3File.TagHandler.Title
    62. _newRow.Track = _mp3File.TagHandler.Track
    63. _newRow.Year = _mp3File.TagHandler.Year
    64. _pbCounter += 1
    65. Catch ex As Exception
    66. 'Debug.WriteLine(ex.Message)
    67. End Try
    68. AllFiles_DataTable.Rows.Add(_newRow)
    69. If _pbCounter Mod 100 = 0 Then
    70. FileInfo_TableDataGridView.Invoke(Sub()
    71. FileInfo_TableDataGridView.Refresh()
    72. End Sub)
    73. End If
    74. If _pbCounter Mod 10 = 0 Then
    75. Invoke(Sub()
    76. ToolStripProgressBar1.PerformStep()
    77. End Sub)
    78. End If
    79. Next
    80. Invoke(Sub()
    81. ToolStripProgressBar1.Value = ToolStripProgressBar1.Maximum
    82. End Sub)
    83. End Sub
    84. End Class



    Dadurch bleibt des Form ruckelfrei als wie bei jedem Eintrag zu refreshen!
    Aber des DGV lässt sich nicht scrollen bzw. die rechte Scrollbar ist "gefrohren".
    Mit den Pfeiltasten kann ich scrollen, aber mit dem Mausrad nicht!

    Geht das nicht performanter?

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Morrison“ ()

    OK, also..
    ich hab jetzt das füllen der DataTable in nem Task laufen..
    ..zudem setze ich nach jedem hundertsten Eintrag ein Invoke auf das DataGridView!
    (Jede hundertste Zeile, weil sonst die Form flimmert bei jedem Update)

    in der For Each Schleife steht dann:

    VB.NET-Quellcode

    1. If _pbCounter Mod 100 = 0 Then
    2. FileInfo_TableDataGridView.Invoke(Sub()
    3. FileInfo_TableDataGridView.Refresh()
    4. FileInfo_TableDataGridView.PerformLayout()
    5. End Sub)
    6. End If


    Also: Das ".PerformLayout()" ist wichtig!! -Zeigt aber des IntelliSense auch nicht an! :huh:
    Was bringt es denn überhaupt da alle Nase was zu aktualisieren? Wäre eine Ladeanzeige bis alles fertig ist nicht besser? Kann denn der User während des Ladens da sinnvolle Dinge mit den bereits vorhandenen Daten tun? Falls nicht, lass es lieber weg. Die Leut klicken erfahrungsgemäß gerne wild rum und tun wirre Dinge …
    "Gib einem Mann einen Fisch und du ernährst ihn für einen Tag. Lehre einen Mann zu fischen und du ernährst ihn für sein Leben."

    Wie debugge ich richtig? => Debuggen, Fehler finden und beseitigen
    Wie man VisualStudio nutzt? => VisualStudio richtig nutzen