2 C#后台工作人员,锁定UI和崩溃(1个后台工作者很好)

时间:2014-09-09 11:26:29

标签: c# multithreading backgroundworker ui-thread

我正在尝试在WPF中使用2个后台工作程序但是“微调器”似乎锁定了UI线程,这阻止了进度条的移动。在我的“加载数据”功能中,它似乎偶尔会导致我的并行for循环崩溃。如果我不启动微调器的背景工作者,一切似乎都能正常工作。

我的微调背景工作者有什么问题?

(这是我第一次和背景工作者一起玩)

    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;


    }

这些是我的openData函数

    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;                            
    }

这些是我的微调功能

    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;
            }
        } 

    }

感谢您提供任何指导

1 个答案:

答案 0 :(得分:1)

您可以对BackgroundWorker的DoWork使用内联调用,请尝试:

    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;
                }
            } 
}));   


        }