none
Backgroundworker

    Question

  • I have a WPF application which is getting data from WCF.

    I also have a grid control in the WPF app. Now I wish to add data to this grid when there is new data in DB. So I wish to have a backgroundworker to check if there is new data, and if so, update the grid. BUt how can I do multi-threading or backgroundowrker in UI thread. I don't quite understand the Dispatcher, UI thread thing. Can someone please provide with some good example.

    TIY

    Monday, January 03, 2011 8:22 AM

Answers

  • Hi Xaria,

    You are not able to access UI elements directly from a BackgroundWorker to do so you have to use Dispatcher. WPF objects which derive from DependencyObject have thread affinity which means that only the thread that instantiates them can access their members.

    In the following example you can find two different approaches:

    • worker refreshes UI instantly using Dispatcher (no direct access to the UI from DoWork event handler)
    • worker1 performs all calculations and sends results to the RunWorkerCompleted event handler (direct access to the UI from RunWorkerCompleted event handler) 

    namespace BackgroundWorker001
    {
      public partial class MainWindow : Window
      {
        int i = 0;
        int j = 0;
        private BackgroundWorker worker;
        private BackgroundWorker worker1;
    
        public MainWindow()
        {
          InitializeComponent();
          worker = new BackgroundWorker();
          worker.DoWork += new DoWorkEventHandler(worker_DoWork);
          worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
          
          worker1 = new BackgroundWorker();
          worker1.DoWork += new DoWorkEventHandler(worker_DoWork1);
          worker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
    
          worker1.RunWorkerAsync();
          worker.RunWorkerAsync();
        }
    
        void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
          if (e.Result != null)
          {
            text1.Text += e.Result;
            text1.Text += " Done!";
          }
          else
            text.Text += " Done!";
        }
    
        void worker_DoWork(object sender, DoWorkEventArgs e)
        {
          while (i < 100)
          {
            i += 5;
            Thread.Sleep(300);
            Dispatcher.BeginInvoke(new Action<int>(UIThreadMethod), DispatcherPriority.Normal, i);
          }
        }
    
        void worker_DoWork1(object sender, DoWorkEventArgs e)
        {
          string result = string.Empty;
          while (j < 100)
          {
            j += 10;
            result += " " + j;
            Thread.Sleep(300);
          }
          e.Result = result;
        }
    
        private void UIThreadMethod(int i)
        {
          text.Text += " " + i;
        }
      }
    }
    
    <Window x:Class="BackgroundWorker001.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
      <StackPanel>
        <TextBlock x:Name="text"/>
        <TextBlock x:Name="text1"/>
      </StackPanel>
    </Window>

    Regards,


    PaVZaV

    http://pavzav.blogspot.com/

    Monday, January 03, 2011 10:18 AM
  • Hi,

    Seems that its a continuous process when ever a  new data comes up your UI needs to get refreshed. Background worker is a single process and will finish after a job gets done. You need some background thread always running and checking if new data exists or not. the when ever you have a new data call a UI method with requredInvode check and then invoke the method passing the new data. Thats a pull data method. You can also implement comet like feature in this context.

    Please follow the following tread

    http://social.msdn.microsoft.com/Forums/en-US/winforms/thread/dc369dc6-716d-464f-b979-495fd9c7182c/

    for more information on background worker please follow the msdn

    http://msdn.microsoft.com/en/library/system.componentmodel.backgroundworker.aspx


    Md. Masudur Rahman
    Monday, January 03, 2011 10:28 AM

All replies

  • Hi Xaria,

    You are not able to access UI elements directly from a BackgroundWorker to do so you have to use Dispatcher. WPF objects which derive from DependencyObject have thread affinity which means that only the thread that instantiates them can access their members.

    In the following example you can find two different approaches:

    • worker refreshes UI instantly using Dispatcher (no direct access to the UI from DoWork event handler)
    • worker1 performs all calculations and sends results to the RunWorkerCompleted event handler (direct access to the UI from RunWorkerCompleted event handler) 

    namespace BackgroundWorker001
    {
      public partial class MainWindow : Window
      {
        int i = 0;
        int j = 0;
        private BackgroundWorker worker;
        private BackgroundWorker worker1;
    
        public MainWindow()
        {
          InitializeComponent();
          worker = new BackgroundWorker();
          worker.DoWork += new DoWorkEventHandler(worker_DoWork);
          worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
          
          worker1 = new BackgroundWorker();
          worker1.DoWork += new DoWorkEventHandler(worker_DoWork1);
          worker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
    
          worker1.RunWorkerAsync();
          worker.RunWorkerAsync();
        }
    
        void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
          if (e.Result != null)
          {
            text1.Text += e.Result;
            text1.Text += " Done!";
          }
          else
            text.Text += " Done!";
        }
    
        void worker_DoWork(object sender, DoWorkEventArgs e)
        {
          while (i < 100)
          {
            i += 5;
            Thread.Sleep(300);
            Dispatcher.BeginInvoke(new Action<int>(UIThreadMethod), DispatcherPriority.Normal, i);
          }
        }
    
        void worker_DoWork1(object sender, DoWorkEventArgs e)
        {
          string result = string.Empty;
          while (j < 100)
          {
            j += 10;
            result += " " + j;
            Thread.Sleep(300);
          }
          e.Result = result;
        }
    
        private void UIThreadMethod(int i)
        {
          text.Text += " " + i;
        }
      }
    }
    
    <Window x:Class="BackgroundWorker001.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
      <StackPanel>
        <TextBlock x:Name="text"/>
        <TextBlock x:Name="text1"/>
      </StackPanel>
    </Window>

    Regards,


    PaVZaV

    http://pavzav.blogspot.com/

    Monday, January 03, 2011 10:18 AM
  • Hi,

    Seems that its a continuous process when ever a  new data comes up your UI needs to get refreshed. Background worker is a single process and will finish after a job gets done. You need some background thread always running and checking if new data exists or not. the when ever you have a new data call a UI method with requredInvode check and then invoke the method passing the new data. Thats a pull data method. You can also implement comet like feature in this context.

    Please follow the following tread

    http://social.msdn.microsoft.com/Forums/en-US/winforms/thread/dc369dc6-716d-464f-b979-495fd9c7182c/

    for more information on background worker please follow the msdn

    http://msdn.microsoft.com/en/library/system.componentmodel.backgroundworker.aspx


    Md. Masudur Rahman
    Monday, January 03, 2011 10:28 AM