Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: WPF multithreading , +
Hi,
I want to show a loading icon in my wpf application when application is busy.
To implementing this I have taken a background worker and showing my loading image on BackgroundWorker_DoWork() event.
 
For Example: on save button click of wpf form process is something like this:
 
1. Have some ui controls like text box, lables and check boxes on the form.
2. On the save button I am sending the data in to database.
3. When save button is clicked then bgworker_dowork() is called and savedata() function is executed but as I getting the control value then it throws an error:
 
"The calling thread cannot access this object because a different thread owns it".
 
4. Here I understand that this error is coming because thread id has been changed. but unable to sort out this error.
 
Sample code as following
My backgroundworker class
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.ComponentModel;
using LoadingControl;
using System.Windows.Forms;
 
namespace LoadingClass
{
    public class BackgroundLoading
    {
        public delegate void RunFunction();
 
        public BackgroundWorker Bw;
        public RunFunction thisFunction;
        LoadingWindow newLoading;
 
        public BackgroundLoading(RunFunction newFunction)
        {
            try
            {
                thisFunction = newFunction;
                Bw = new BackgroundWorker();
                Bw.DoWork += new DoWorkEventHandler(Bw_DoWork);
                Bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(Bw_RunWorkerCompleted);                
            }
            catch (Exception ex)
            {
                throw;
            }
        }
 
        public void Start()
        {
            try
            {
                Bw.RunWorkerAsync();
                newLoading = new LoadingWindow();
                newLoading.ShowDialog();
            }
            catch (Exception ex)
            {
                throw;
            }
        }
 
        void Bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            try
            {
                newLoading.Close();
            }
            catch (Exception ex)
            {
                throw;
            }
        }
 

        void Bw_DoWork(object sender, DoWorkEventArgs e)
        {
            try
            {
                if (thisFunction != null)
                {
                    thisFunction();
                }
            }
            catch (Exception ex)
            {
                throw;
            }
        }
    }
}

 

code on my wpf form is something like this

public void btnSave_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                if (Validator.IsValid(this))
                {
                    BackgroundLoading BL = new BackgroundLoading(SavePatient); 
                    BL.Start();
                }
            }
            catch (Exception ex)
            {
                Common.WriteToErrorLog(ex.Message, "btnSave_Click");
            }
        }
 
public void SavePatient()
        {
txtAge.Text = txtAge.Text; // error is coming in this line
}
 
Please suggest if you have any solution...
 
Thanks in advance
Posted 5-Sep-12 21:39pm
Edited 5-Sep-12 21:51pm
v6
Comments
Sergey Alexandrovich Kryukov at 6-Sep-12 2:42am
   
BackgroundWorker_DoWork is not an event. Surprised?
--SA
harish kr chandna at 6-Sep-12 2:52am
   
I have updated my question.
Sergey Alexandrovich Kryukov at 6-Sep-12 13:22pm
   
Thank you, I'll take a look now...
--SA
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 2

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;
using System.Windows.Threading;
 

namespace TestLoading
{
    /// AMIT KUMAR JHA

 
    public partial class Window1 : Window
    {
        public decimal Idx;
        public decimal Maximum = 90000000;
        decimal nudShowResult;
        DispatcherTimer dispatcherTimer = new DispatcherTimer();
        BackgroundWorker bWorker1 ;
        FrmLoding LoadingForm = new FrmLoding();
 
        public Window1()
        {
            InitializeComponent();           
           
        }
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
 
        }
        private void dispatcherTimer_Tick(object sender, EventArgs e)
        {
            nudShowResult =Idx;
            
        }
 
        private void worker_DoWork(object sender, DoWorkEventArgs e)
        {
            decimal ThisMaxValue = Maximum;
            if (e.Argument != null && e.Argument is decimal)
                ThisMaxValue = (decimal)e.Argument;
            //This run in a new thread
            for (int i = 0; i <= ThisMaxValue; i++)
            {
                Idx = i;
            }
        }
 
        private void worker_RunWorkerCompleted(object sender,RunWorkerCompletedEventArgs e)
        {
            nudShowResult = Idx;
              dispatcherTimer.Stop();
              bWorker1.RunWorkerAsync();
                if (LoadingForm != null && LoadingForm.IsVisible)
                    //
                    LoadingForm.Close();
 
            
        }
 
        private void btnShow_Click(object sender, RoutedEventArgs e)
        {
            bWorker1 = (BackgroundWorker)this.FindResource("backWorker");
            dispatcherTimer.Start();
            bWorker1.RunWorkerAsync();         
            LoadingForm.ShowDialog();
        }
 
       
      
        public void Counter()
        {
            for (int i = 0; i <= Maximum; i++)
            {
                Idx = i;
            }
        }
    }
}
  Permalink  
v2
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 3

// AMIT KUMAR JHA
 

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:wpfx="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit/extended"
Title="Window1" Height="300" Width="500" Loaded="Window_Loaded">



 

 

<button content="Start Processing" height="40" horizontalalignment="Left" margin="78,12,0,0" name="StartButton" verticalalignment="Top" width="100" click="StartButton_Click" />
<button content="Stop Processing" height="40" horizontalalignment="Left" margin="237,12,0,0" name="StopButton" verticalalignment="Top" width="100" click="StopButton_Click" />


 

-------------------------Code-----------------------------

using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;
 
namespace TestBusyIndicator
{

public partial class Window1 : Window
{
DispatcherTimer dispatcherTimer = new DispatcherTimer();
 
public Window1()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick);
dispatcherTimer.Interval = new TimeSpan(0, 0, 2);
}
 
private void StartButton_Click(object sender, RoutedEventArgs e)
{
dispatcherTimer.Start();
BusyBar.IsBusy = true;

}
 
private void dispatcherTimer_Tick(object sender, EventArgs e)
{
listBox1.Items.Add(DateTime.Now.Hour.ToString() + ":" +
DateTime.Now.Second.ToString());
 
CommandManager.InvalidateRequerySuggested();
listBox1.Items.MoveCurrentToLast();
listBox1.SelectedItem = listBox1.Items.CurrentItem;
listBox1.ScrollIntoView(listBox1.Items.CurrentItem);
}
 
private void StopButton_Click(object sender, RoutedEventArgs e)
{
dispatcherTimer.Stop();
BusyBar.IsBusy = false;
}
 
public void SavePatient()
{

}
}
}
  Permalink  
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

  Permalink  
v4
Comments
harish kr chandna at 6-Sep-12 3:17am
   
giving a new error:
 
Cannot implicitly convert type 'LoadingClass.BackgroundLoading' to 'System.ComponentModel.BackgroundWorker'
Sangramsingh Pawar at 6-Sep-12 3:25am
   
upps sorry,
it's my mistake remove this and use your code
Sergey Alexandrovich Kryukov at 6-Sep-12 13:25pm
   
This answer contains one real crime: excessive catch and throwing exception. This code is logically strictly equivalent to not handling any exceptions here, only wastes time. It's the best just to not handling any exceptions here. As you apparently have no idea how to use exceptions and try to mislead OP (please, everyone: never do exception handling the wrong way demonstrated in this code sample), I just had to vote 1, sorry.
--SA
harish kr chandna at 7-Sep-12 1:19am
   
yes know that..
 
actually no need for try and catch block here, because we know what the exception will say, that can be added later.. at this point we need how to sort out the problem..
 
thanks
Sergey Alexandrovich Kryukov at 7-Sep-12 13:52pm
   
True.
--SA

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
0 OriginalGriff 350
1 Jochen Arndt 190
2 Richard MacCutchan 135
3 Sergey Alexandrovich Kryukov 130
4 DamithSL 95
0 OriginalGriff 6,045
1 DamithSL 4,601
2 Maciej Los 4,087
3 Kornfeld Eliyahu Peter 3,480
4 Sergey Alexandrovich Kryukov 3,310


Advertise | Privacy | Mobile
Web01 | 2.8.141220.1 | Last Updated 30 Jul 2013
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100