wpfvb.netbackgroundworkerui-threadbegininvoke

Update UI from another window BackgroundWorker vb.net WPF


I am working on a wpf project...I've faced similar issues in the past,but didn't get the answer to it and that's why i'm asking again :)

My WPF app has 2 windows,one works as a splash screen and the 2nd one is just a basic window with a canvas.The splash screen has a BackGroundWorker.Now,i have this code :

  Dim h2 as new Window2
  For Each fi As FileInfo In New DirectoryInfo(Application.StartupPath + 
  "\data\img\em_sml").GetFiles()

  h2.canvas.children.add(new Button)

Now, my question is how do i use this code in the backgroundworker in Window1 ?? I tried this :

 Dim method as Delegate
 Private Sub BgWorker_DoWork(sender As Object, e As DoWorkEventArgs) Handles BgWorker.DoWork

 If h2.Dispatcher.CheckAccess Then      
  For Each fi As FileInfo In New DirectoryInfo(Application.StartupPath + 
  "\data\img\em_sml").GetFiles()
  h2.canvas.children.add(new Button)

 Else

  h2.Dispatcher.BeginInvoke(DispatcherPriority.Normal, method)
  For Each fi As FileInfo In New DirectoryInfo(Application.StartupPath + 
  "\data\img\em_sml").GetFiles()

  h2.canvas.children.add(new Button)

 End if

A few things i'ld like to clear here :

• I got the sample code from another SO post(i converted it from c#)

Dim method as Delegate,i don't really know how to use a delegate function

• The code above returns some exceptions like Parameter name:Method , Value can not be null(I know what this means but as i said,i don't know how i can use the delegate function in such a case)

Any help would be appreciated


Solution

  • The code you're using is trying to invoke to the UI thread via Dispatcher.BeginInvoke(). This is the way to do it in threads, but not in a BackgroundWorker. In a BGW you're supposed to call the ReportProgress() method combined with subscribing to the ProgressChanged event.

    However for what you're trying to do, this is not good at all...

    For starters: You should NEVER create controls in a background thread! All work related to the UI (User Interface) must always, always, always be done on the UI thread ONLY.

    Secondly: There isn't really a good reason for trying to do this in a background thread. The way you're doing it now constantly updates the UI thread, causing it to lag/freeze anyway. What you could do to minimize the lag is to add the buttons in batches, but then as I said before you shouldn't be creating controls in a background thread at all.

    Finally: The whole operation of iterating a few files and creating buttons for them really isn't very heavy. Unless you have thousands of files (in which case you should only display them in batches) this will not take that long to perform on the UI thread.

    Conclusion: Skip the BackgroundWorker and run your code on the UI thread instead. If you have a really huge amount of files to load, store their paths in a list, only load them in batches and let the user decide when to load the next batch of files.