无法将 BackgroundWorker 进度百分比调整为任务的实际百分比

Posted

技术标签:

【中文标题】无法将 BackgroundWorker 进度百分比调整为任务的实际百分比【英文标题】:Cannot Adapt BackgroundWorker progress percentage to the real percentage of the task 【发布时间】:2015-06-29 13:28:49 【问题描述】:

我编写了一个程序,它读取一个短视频,然后以降低的 FPS 写入几百帧。它运行良好,但“if”循环阻塞了 UI。我尝试创建一个 backgroudWorker 来处理“if”循环,同时可以显示 UI 值,并且可以通过“取消”按钮中断该过程。 我的问题是:我无法让“if”循环遍历所有帧:

for (i = 0; i < frames_number; i++)

到最后一帧!它停在 100,即使我尝试了多种解决方案将“i”的进度转换为百分比,例如:

progress = System::Convert::ToInt32((100*(i / frames_number)));

progress = (int)((float)i / (float)frames_number *100);

以下是代码的重要sn-ps:

private: System::Void CreateSlowMo_Click(System::Object^  sender, System::EventArgs^  e) 
        VideoCapture inputVideo(videoToOpenNameStr);
        if (!inputVideo.isOpened()) 
            MessageBox::Show(L"Error"); 
               
        fps =   int(inputVideo.get(CAP_PROP_FPS)); // get the frame rate of the video
        frames_number = int(inputVideo.get(CAP_PROP_FRAME_COUNT));     // get the total frames in the video
        this->progressBar1->Maximum = frames_number;      // Initilize the progress bar's maximum to the number of frames       
        outputVideo.open(name, CV_FOURCC('M', 'J', 'P', 'G'), fps_wanted, resolution, true);  // Create an output video 
        if (outputVideo.isOpened())
           
            this->backgroundWorker1->RunWorkerAsync(progress);     // Delegating the blocking operations to the background worker        
        
        else 
            MessageBox::Show(L"Error creating the video");
            CreateSlowMo_button->Enabled = true;
               
    

backgroundWorker1_DoWork:

private: System::Void backgroundWorker1_DoWork(System::Object^  sender, System::ComponentModel::DoWorkEventArgs^  e) 

    progress = (int)e->Argument; // get the intial value of the argument
    for (i = 0; i < frames_number; i++)
        
        inputVideo >> source; // read frame 

        if (backgroundWorker1->CancellationPending)    // check if the User clicked on "Cancel"
            e->Cancel = true;
            break;    // Stop the convertion
        
        if (source.empty())  // we reached the last frame
            break;
            //  CreateSlowMo_button->Enabled = true;
            
        if (progress > 100) 
         // verify we didn't exceed 100% of the task
            backgroundWorker1->ReportProgress(100);
            break;
               
        outputVideo << source; // write the frame to the output video
        progress = (int)(((float)i / (float)frames_number)* 100);
        backgroundWorker1->ReportProgress(progress);        
         
    this->backgroundWorker1->ReportProgress(100);
    e->Result = progress;    

backgroundWorker1_ProgressChanged:

private: System::Void backgroundWorker1_ProgressChanged(System::Object^  sender, System::ComponentModel::ProgressChangedEventArgs^  e) 
    this->progressBar1->Value = e->ProgressPercentage;
    toolStripStatusLabel1->Text = "Processing..." + progressBar1->Value.ToString() + "%";
    richTextBox6->Text = e->ProgressPercentage.ToString();  

backgroundWorker1_RunWorkerCompleted:

private: System::Void backgroundWorker1_RunWorkerCompleted(System::Object^  sender, System::ComponentModel::RunWorkerCompletedEventArgs^  e) 
     // in case the background process is finished with a cancel
    if (e->Cancelled) 
    
        toolStripStatusLabel1->Text = "Task Cancelled";
    
    // check if an error occurred in the backgroud process
    else if (e->Error != nullptr)
     
        toolStripStatusLabel1->Text = "Error while creating the SlowMo";
    
    else 
       // task completed normally
        this->toolStripStatusLabel1->Text = "SlowMo Created successfully!";
        this->cancel_button->Enabled = false;
        MessageBox::Show(L"Finished creating the sloMo");
        this->toolStripStatusLabel1->Text = "Done";
        this->CreateSlowMo_button->Enabled = true;   
        this->richTextBox5->Text = "value " + e->Result;
    

这里是结果的一些截图(我添加了文本框来可视化 'i'、'progress' 和 e->result 的值)'i' 和 'progress' 是 int=0,在文件 'variables 中定义.h'

extern int i ;
extern int progress;

和'variables.cpp':

int i = 0;
int progress =0;

【问题讨论】:

您的代码中有一个明显的错误,您正在从 0..100 计算进度,但 ProgressBar::Maximum 不是 100。简单的解决方法是删除 this-&gt;progressBar1-&gt;Maximum = frames_number; 分配。跨度> 我改变了它,但它只影响了progressBar(它是完全绿色的)并且不能通过所有的帧(这里是589)。结果如下:i.imgur.com/H6rP9xZ.pngi.imgur.com/wYAYKSO.png 【参考方案1】:

您检查过frames_number 的值吗?或者,如果您在for 循环中的任何if 语句在执行期间的任何时候变为真?

我怀疑frames_numberfor 循环之前获得了不正确的值,或者source.empty() 变为真。

【讨论】:

以上是关于无法将 BackgroundWorker 进度百分比调整为任务的实际百分比的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 C# BackgroundWorker 报告本机 C++ 代码的进度?

BackgroundWorker 组件 -- 进度条

BackgroundWorker UI不会更新Windows Phone 7中的进度

如何为无法获取进度百分比的耗时操作增加“伪进度条”?

C# BackGroundWorker实现窗体不卡死 进度条功能

使用后台线程BackgroundWorker处理任务的总结