【问题标题】:Update two (individual operation/total operation) progressbars in GUI using BackgroundWorker?使用 BackgroundWorker 更新 GUI 中的两个(单个操作/总操作)进度条?
【发布时间】:2016-04-17 02:10:16
【问题描述】:

好吧,我一整天都在努力解决这个问题。我对编程还是很陌生,很可能我的整个方法都被误导了。但无论如何......所以我有一个简单的 gui 应用程序,其中包含一个充满文件夹的列表框,并且我正在按顺序对每个文件夹中的每个文件执行操作。这是一个很长的操作,所以我有两个进度条 - 每个文件一个,每个文件夹一个。

private void buttonApplySelected_Click(object sender, EventArgs e)
{
    backgroundWorker1.RunWorkerAsync();
}

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
     double percentToIncrement = 100.0 / Convert.ToDouble(selectedDirList.Count);
     double percentComplete = percentToIncrement;
     folderProgressBar.Value = 0;
     foreach (string dir in selectedDirList)
     {
             engine = new OEngine.OEngine(dir, backgroundWorker1);
             engine.ProcessSelected(processType);

             int percentCompleteInt = Convert.ToInt32(percentComplete);
             folderProgressBar.Value = percentCompleteInt;
             percentComplete += percentToIncrement;
     }         
}

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
     fileProgressBar.Value = e.ProgressPercentage;
}

BackgroundWorker 本身被传递给引擎,并在引擎处理该文件夹的代码中更新其进度。 (这可能是我的第一个错误。)UI 捕获 ProgressChanged 事件并在它自己的线程中更新 fileProgressBar。

但是每次通过for循环都需要更新folderProgressBar,但它给了我Cross-thread operation not valid: Control 'folderProgressBar' accessed from a thread other than the thread it was created on.

如果我将它移出 for 循环,它不会在每个文件夹之后更新。 如果我将所有 UI 更新移出 DoWork 函数,而是在 for 循环中调用 DoWork 函数,它显然不会等待每个文件夹完成并且我得到“工作人员仍然很忙”异常。

有什么想法吗?

【问题讨论】:

    标签: c# multithreading


    【解决方案1】:

    windows窗体的通用解决方案: 使用

    WindowsFormsSynchronizationContext syncContext = new WindowsFormsSynchronizationContext();
    

    ...

    //in the background work or any non UI Thread
    
    //Trigger an update in the GUI thread; one can also use syncContext.Send (depending on the need for syncrhonous or async operation)
    syncContext.Post(UpdateGUI, userData);
    
    ...
    
    void UpdateGUI(object userData)
    {
      //update your progress bar 
    }
    
    If using wpf, declare a variable syncContex.
    
    SynchronizationContext syncContext;
    //And when in the UI thread, set the variable's value as
    syncContext = SynchronizationContext.Current;
    
    //Then from the non-UI thread, 
    syncContext.Post(UpdateGUI, userData);
    

    【讨论】:

    • 我并不完全了解每个代码块的去向。
    猜你喜欢
    • 2014-10-14
    • 1970-01-01
    • 1970-01-01
    • 2011-09-12
    • 1970-01-01
    • 2013-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多