首页 > 解决方案 > C++ Visual Studio 2017 表单。如何从单独的线程更新和刷新标签

问题描述

我尝试使用一些方法,但似乎无法将标签传递给新线程,或者让辅助线程能够访问标签并刷新表单线程上的表单。我正在尝试使其具有多线程,以便在对远程设备运行命令时界面不会锁定。任何有助于更新标签并从辅助线程刷新表单的方法将不胜感激!这是我的 MyForm.h 文件和 MyForm.cpp 文件:

#include <iostream>
#include <conio.h>
#include <windows.h>


namespace StudioControl2 {

    using namespace System;
    using namespace System::ComponentModel;
    using namespace System::Collections;
    using namespace System::Windows::Forms;
    using namespace System::Data;
    using namespace System::Drawing;
    using namespace System::Threading;
    using namespace System::Threading::Tasks;
    using namespace std;

    bool GUIEvent = false;

    /// <summary>
    /// Summary for MyForm
    /// </summary>
    public ref class MyForm : public System::Windows::Forms::Form
    {
    public:
        MyForm (void)
        {
            InitializeComponent();
            //
            //TODO: Add the constructor code here
            //
        }

    protected:
        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        ~MyForm()
        {
            if (components)
            {
                delete components;
            }
        }

    private: System::Windows::Forms::Button^  WindowTVVmixSelect;
    private: System::Windows::Forms::Label^  StatusOutput;


    private: System::ComponentModel::IContainer^  components;
    protected:

    private:
        /// <summary>
        /// Required designer variable.
        /// </summary>


#pragma region Windows Form Designer generated code
        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        void InitializeComponent(void)
        {
            System::ComponentModel::ComponentResourceManager^  resources = (gcnew System::ComponentModel::ComponentResourceManager(MyForm::typeid));
            this->WindowTVVmixSelect = (gcnew System::Windows::Forms::Button());
            this->StatusOutput = (gcnew System::Windows::Forms::Label());
            (cli::safe_cast<System::ComponentModel::ISupportInitialize^>(this->pictureBox1))->BeginInit();
            this->SuspendLayout();
            // 
            // WindowTVVmixSelect
            // 
            this->WindowTVVmixSelect->Anchor = System::Windows::Forms::AnchorStyles::None;
            this->WindowTVVmixSelect->Location = System::Drawing::Point(31, 400);
            this->WindowTVVmixSelect->Margin = System::Windows::Forms::Padding(5);
            this->WindowTVVmixSelect->Name = L"WindowTVVmixSelect";
            this->WindowTVVmixSelect->Size = System::Drawing::Size(120, 30);
            this->WindowTVVmixSelect->TabIndex = 10;
            this->WindowTVVmixSelect->Text = L"Vmix";
            this->WindowTVVmixSelect->UseVisualStyleBackColor = true;
            this->WindowTVVmixSelect->Click += gcnew System::EventHandler(this, &MyForm::WindowTVVmixSelect_Click);
            // 
            // StatusOutput
            // 
            this->StatusOutput->Anchor = System::Windows::Forms::AnchorStyles::None;
            this->StatusOutput->BorderStyle = System::Windows::Forms::BorderStyle::Fixed3D;
            this->StatusOutput->ForeColor = System::Drawing::Color::Red;
            this->StatusOutput->Location = System::Drawing::Point(232, 612);
            this->StatusOutput->Margin = System::Windows::Forms::Padding(5);
            this->StatusOutput->Name = L"StatusOutput";
            this->StatusOutput->Size = System::Drawing::Size(120, 30);
            this->StatusOutput->TabIndex = 20;
            this->StatusOutput->TextAlign = System::Drawing::ContentAlignment::MiddleCenter;
            // 
            // MyForm
            // 
            this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
            this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
            this->ClientSize = System::Drawing::Size(584, 661);
            this->Controls->Add(this->WindowTVVmixSelect);
            this->MinimumSize = System::Drawing::Size(600, 700);
            this->Name = L"MyForm";
            this->Text = L"Studio Control";
            (cli::safe_cast<System::ComponentModel::ISupportInitialize^>(this->pictureBox1))->EndInit();
            this->ResumeLayout(false);
            this->PerformLayout();

        }
#pragma endregion

private: System::Void WindowTVVmixSelect_Click(System::Object^  sender, System::EventArgs^  e) {

    if (GUIEvent == false) {
    GUIEvent = true;
    Console::WriteLine("Window TV Vmix Select");
    WindowHDMIStatus -> Text = "Vmix";
    StatusOutput->Text = "Please Wait";
    MyForm::Refresh();
//Creation of new thread.
    ThreadWindowTVVmixSelect^ o1 = gcnew ThreadWindowTVVmixSelect();
    Thread^ t1 = gcnew Thread(gcnew ThreadStart(o1, &ThreadWindowTVVmixSelect::ThreadEntryPoint));
    t1->Name = "t1";
    t1->Start();
    }
}


        ref class ThreadWindowTVVmixSelect
        {
        public:
            void ThreadEntryPoint()
            {
                Sleep(2000);
                Console::WriteLine("Terminating Thread Window TV Vmix Select");

                //Trying to update and refresh label in MyForm.

                GUIEvent = false;
            }
        };
};
}
#include "MyForm.h"

using namespace System;
using namespace System::Windows::Forms;

[STAThreadAttribute]
int main(array<String^>^ args) {
    Application::EnableVisualStyles();
    Application::SetCompatibleTextRenderingDefault(false);
    StudioControl2::MyForm form;
    Application::Run(%form);
    return 0;
}

标签: multithreadingformslabelc++-cli

解决方案


如此处所示MS Docs Forms Invoker

您需要创建所谓的调用程序,以调用您在创建他的线程中给他的命令,因此它是委托。

编辑:

我没有意识到它是 cpp,语法有点不同,但主要思想是相同的, Define 和 ise 代表 MS Doc


推荐阅读