Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/137.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在VisualC++中从非托管代码更新托管表单_C++_Visual Studio 2010_Backgroundworker - Fatal编程技术网

在VisualC++中从非托管代码更新托管表单

在VisualC++中从非托管代码更新托管表单,c++,visual-studio-2010,backgroundworker,C++,Visual Studio 2010,Backgroundworker,我有一个Windows窗体,当您单击窗体上的按钮时,它会运行一个测试EngTest\u F。此函数是从本机DLL调用的。我还在托管表单代码中创建了一个backgroundworker,它调用函数GetSicStatusMsg来更新表单中的文本框 在我的原生EngTest_F函数中,我有一些函数可以将文本更新推送到字符串队列中。然后,当调用GetSicStatusMsg时,它检查队列中的字符串,并将它们打印到windows窗体中的richTextBox中 我需要做的是让backgroundwork

我有一个Windows窗体,当您单击窗体上的按钮时,它会运行一个测试EngTest\u F。此函数是从本机DLL调用的。我还在托管表单代码中创建了一个backgroundworker,它调用函数GetSicStatusMsg来更新表单中的文本框

在我的原生EngTest_F函数中,我有一些函数可以将文本更新推送到字符串队列中。然后,当调用GetSicStatusMsg时,它检查队列中的字符串,并将它们打印到windows窗体中的richTextBox中

我需要做的是让backgroundworker持续运行GetSicStatusMsg,这样我就可以获得测试运行方式的实时进度。实际发生的情况是,EngTest_F运行,然后在完成后大约一秒钟,所有状态消息都会立即打印出来

有没有办法完成我想做的事?还是有更简单的方法?这是我第一次使用线程,文档有点缺乏

    private: void GetSicStatusMsg()
         {
             try
             {
                 while(GetNumStatusMsgs())
                 {
                     String^ Status = gcnew String(GetStatusMsg().c_str());
                     DisplayStatus(Status, DISPLAY_SIC);
                 }
             }
             catch(SIC_Error *Err)
             {
                 if(Err->ErrorCode != NO_CONTROLLER)
                 {
                     String^ Error = gcnew String(Err->ErrorMsg.c_str());
                     DisplayStatus(Error,DISPLAY_SIC);
                 }
             }
             catch(Exception ^Ex)
             {
                 DisplayStatus(Ex->Message,DISPLAY_SIC);
             }
         }

    private: System::Void button1_Click(System::Object^  /*sender*/, System::EventArgs^  /*e*/) 
         {      
             this->button1->Enabled = false;

             // Enable the Cancel button while 
             // the asynchronous operation runs.
             this->button4->Enabled = true;

             // Start the asynchronous operation. Needs to be running while EngTest_F is running
             backgroundWorker1->RunWorkerAsync();

             EngTest_F();
         }

    private: System::Void backgroundWorker1_ProgressChanged(System::Object^  sender, System::ComponentModel::ProgressChangedEventArgs^  e) 
         {
             GetSicStatusMsg();
         }

    private: void backgroundWorker1_RunWorkerCompleted( Object^ sender, RunWorkerCompletedEventArgs^ e )
         {
             // Enable the Start button.
             button1->Enabled = true;

             // Disable the Cancel button.
             button4->Enabled = false;
         }

    private: void backgroundWorker1_DoWork( Object^ sender, DoWorkEventArgs^ e )
         {
             // Get the BackgroundWorker that raised this event.
             BackgroundWorker^ worker = dynamic_cast<BackgroundWorker^>(sender);

             worker->ReportProgress(0);
         }

看起来你的代码是反向的。UI线程应该更新UI,后台线程应该执行长时间运行的任务,我想这就是EngTest\u F。实现这一点的一种方法是使用System.Windows.Forms.Timer组件。设置一个间隔为50左右的计时器,该计时器调用GetSicStatusMsg来更新UI。任务启动时启用计时器,任务完成时禁用计时器


我不是BackgroundWorker方面的专家,我自己倾向于使用普通的线程对象,但我敢打赌,每当任务进行时,您都需要调用ReportProgress;您的代码只调用ReportProgress一次。我建议在您的情况下使用普通线程+计时器,因为您的非托管代码可能很难调用BackgroundWorker.ReportProgress。

您调用ReportProgress的频率可能太高,UI线程中充斥着调用请求,因此它无法再执行正常任务。通过添加System::Threading::Thread::Sleep50检查这一点;在ReportProgress调用之后。如果这解决了问题,那么就以人眼可以感知的速度报告进展情况。每秒不超过20次。我想你是对的,制作一个自定义线程看起来是一种方式——backgroundworker与其说是一种方便,不如说是一种麻烦!最后我创建了两个线程,一个用于EngTest\u F,另一个用于GetSicStatusMsg。为了在EngTest\u F完成后停止GetSicStatusMsg线程,我刚刚创建了一个bool变量“test\u finished”,该变量在EngTest\u F完成时设置为true。然后我在GetSicStatusMsg的while循环中使用test_finished作为不变量,因此它一直运行到test_finished=true