Click here to Skip to main content
15,885,141 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more: , +
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
C#
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

C#
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
Updated 5-Sep-12 20:51pm
v6
Comments
Sergey Alexandrovich Kryukov 6-Sep-12 2:42am    
BackgroundWorker_DoWork is not an event. Surprised?
--SA
harish kr chandna 6-Sep-12 2:52am    
I have updated my question.
Sergey Alexandrovich Kryukov 6-Sep-12 13:22pm    
Thank you, I'll take a look now...
--SA

C#
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;
            }
        }
    }
}
 
Share this answer
 
v2
// AMIT KUMAR JHA

<window x:class="TestBusyIndicator.Window1" xmlns:x="#unknown">
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">
<grid>
<wpfx:busyindicator name="BusyBar" margin="134,218,135,0" busycontent="Plese wait. " xmlns:wpfx="#unknown">


<listbox height="148" horizontalalignment="Left" margin="110,64,0,0" name="listBox1" verticalalignment="Top" width="281" itemssource="{Binding}">





-------------------------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()
{

}
}
}
 
Share this answer
 
 
Share this answer
 
v4
Comments
harish kr chandna 6-Sep-12 3:17am    
giving a new error:

Cannot implicitly convert type 'LoadingClass.BackgroundLoading' to 'System.ComponentModel.BackgroundWorker'
Sangramsingh Pawar 6-Sep-12 3:25am    
upps sorry,
it's my mistake remove this and use your code
Sergey Alexandrovich Kryukov 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 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 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)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900