0

I am trying to use 2 background workers in WPF however the "spinner" seems to lock the UI thread which stops the progress bar from moving along. It also seems to cause occasional crashes with my parrallel for loops in the "load data" function I have. If I don't kick off the spinner's background worker, everything seems to work fine.

What is wrong with my spinner background worker?

(this is my first time playing with background workers)

    BackgroundWorker _spinthatspinner = new BackgroundWorker();
    BackgroundWorker _openDataWorker;
    string data_fileName;
    private void Load_Data_Click(object sender, RoutedEventArgs e)
    {

        Microsoft.Win32.OpenFileDialog OFD = new Microsoft.Win32.OpenFileDialog();
        if (OFD.ShowDialog() == true)
        {
            data_fileName = OFD.FileName;

            //set initial state
            this.myDataGrid.IsEnabled = false;
            this.spinner.Visibility = System.Windows.Visibility.Visible;

            dataLoadProg.Minimum = 0;
            dataLoadProg.Maximum = 100;
            dataLoadProg.Visibility = System.Windows.Visibility.Visible;

            //kick off opening the data loader
            _openDataWorker = new BackgroundWorker();
            _openDataWorker.DoWork += _openDataWorker_DoWork;
            _openDataWorker.ProgressChanged += _openDataWorker_ProgressChanged;
            _openDataWorker.RunWorkerCompleted += _openDataWorker_RunWorkerCompleted;
            _openDataWorker.WorkerReportsProgress = true;
            _openDataWorker.RunWorkerAsync();

            //kick off the spinner       
            _spinthatspinner = new BackgroundWorker();
            _spinthatspinner.DoWork += spinner_DoWork;
            _spinthatspinner.ProgressChanged += spinnner_prog;
            _spinthatspinner.RunWorkerCompleted += spinnerSpint_completed;
            _spinthatspinner.WorkerReportsProgress = true;
            _spinthatspinner.RunWorkerAsync(); //if I comment out this, loading bar works fine, no crashes
        }
        return;


    }

These are my openData Functions

    void _openDataWorker_DoWork(object sender, DoWorkEventArgs e)
    {
        System.Diagnostics.Process.GetCurrentProcess().PriorityClass = System.Diagnostics.ProcessPriorityClass.AboveNormal; //tried without and with

        m_currentData = new myData();
        openData(data_fileName, m_currentData);        


    }
    void openData(string filename, myData data)
    {
        //this function is complex but it
        //it basically boils down to this
        //...code omitted..
        while ((line = file.ReadLine()) != null)
        {             
            stringData.AddLine(line);
            percentageF += progressPercentageForEachLine;
            m_openMaldiWorker.ReportProgress((int)percentageF);
        }
        //at this point the progress bar is filled and ideally the spinner would start (but kicking it off here seems to cause more problems)
        data.Load(stringData); //in here I have some parallel for loops to process the data collected

    }   

    //move progress bar along
    void _openDataWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        dataLoadProg.Value = e.ProgressPercentage;
    }
    //enable and fill UI controlls
    void _openDataWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        analysisDataContext.FillWithData(m_currentData);       //ok fill the data grid                
        this.myDataGrid.IsEnabled = true;                            
    }

These are my spinner functions

    void spinnerSpint_completed(object o, RunWorkerCompletedEventArgs args) 
    {  
        this.spinner.Visibility = System.Windows.Visibility.Hidden;

    }
    void spinnner_prog(object sender, ProgressChangedEventArgs e)
    {
        _spinnerRotation.Angle = e.ProgressPercentage;       
    }

    void spinner_DoWork(object o, DoWorkEventArgs args)
    {           
        System.Diagnostics.Process.GetCurrentProcess().PriorityClass = System.Diagnostics.ProcessPriorityClass.Idle; //tried without and with
        float angle = 0;
        bool stopSpinning = m_currentData != null && m_currentData.isLoaded == true;
        while (!stopSpinning )
        {
            //spin something
            angle++;
            if (angle > 360.0f)
            {
                angle = 0.0f;                        
            }

            _spinthatspinner.ReportProgress((int)angle);

            if (m_currentData != null && m_currentData.isLoaded == true)
            {
                stopSpinning = true;
            }
        } 

    }

Thank you for any guidance

chrispepper1989
  • 2,100
  • 2
  • 23
  • 48

1 Answers1

1

you can use inline invocation for BackgroundWorker's DoWork, try :

    void spinner_DoWork(object o, DoWorkEventArgs args)
        {        
this.Dispatcher.BeginInvoke(new Action(() => {
System.Diagnostics.Process.GetCurrentProcess().PriorityClass = System.Diagnostics.ProcessPriorityClass.Idle; //tried without and with
            float angle = 0;
            bool stopSpinning = m_currentData != null && m_currentData.isLoaded == true;
            while (!stopSpinning )
            {
                //spin something
                angle++;
                if (angle > 360.0f)
                {
                    angle = 0.0f;                        
                }

                _spinthatspinner.ReportProgress((int)angle);

                if (m_currentData != null && m_currentData.isLoaded == true)
                {
                    stopSpinning = true;
                }
            } 
}));   


        }
Cem Sönmez
  • 506
  • 1
  • 3
  • 15