C ++ Visual Studio 2017 Форма. Как я могу обновить и обновить ярлык из отдельного потока - PullRequest
0 голосов
/ 13 января 2019

Я пытался использовать несколько методов, но, похоже, не могу передать метку новому потоку или сделать так, чтобы вторичный поток мог получить доступ к метке и обновить форму в потоке формы. Я пытаюсь сделать его многопоточным, чтобы интерфейс не блокировался при запуске команд на удаленные устройства. Мы будем благодарны за любую помощь в обновлении метки и обновлении формы из вторичного потока! Вот мой файл 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;
}

Ответы [ 2 ]

0 голосов
/ 19 января 2019

Я выяснил, как сделать потокобезопасный вызов с того же сайта, о котором я говорил (https://docs.microsoft.com/en-us/dotnet/framework/winforms/controls/how-to-make-thread-safe-calls-to-windows-forms-controls).) В правом верхнем углу страницы есть небольшой символ (</>), который меняет примеры кода на один из трех вариантов: C #, VB или C ++.

Вот код, который я использовал для настройки нового потока и запуска безопасного для потока вызова на метке формы в потоке пользовательского интерфейса из нового потока:

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

    if (GUIEvent == false) {
    GUIEvent = true;
    Console::WriteLine("Window TV Vmix Select");
    StatusOutput->Text = "Please Wait";
    MyForm::Refresh();
    //Creation of new thread.
    this->Thread1 =
        gcnew Thread(gcnew ThreadStart(this, &MyForm::ThreadWindowTVVmixSelect));
    this->Thread1->Start();
    }
}
private:
        void ThreadWindowTVVmixSelect()
        {
            Sleep(3000);
            //SetTextWindowHDMIStatus("Vmix");
            SetTextStatusOutput("");
            GUIEvent = false;
        }
    delegate void StringArgReturningVoidDelegate(String^ text);
             //Sets the status label in the form
             private:
                 void SetTextStatusOutput(String^ text)
                 {
                     // InvokeRequired required compares the thread ID of the
                     // calling thread to the thread ID of the creating thread.
                     // If these threads are different, it returns true.
                     if (this->StatusOutput->InvokeRequired)
                     {
                         StringArgReturningVoidDelegate^ d =
                             gcnew StringArgReturningVoidDelegate(this, &MyForm::SetTextStatusOutput);
                         this->Invoke(d, gcnew array<Object^> { text });
                     }
                     else
                     {
                         this->StatusOutput->Text = text;
                     }
                 }

Надеюсь, это поможет всем, кто хочет обновить форму C ++ CLR из другого потока.

0 голосов
/ 13 января 2019

Как показано здесь MS Docs Forms Invoker

Вам нужно создать так называемый invoker, который будет вызывать команды, которые вы ему дадите, в потоке, который его создал, так что это делегат.

Edit:

Я не осознавал, что это cpp, синтаксис немного другой, но основная идея та же Определение и получение делегатов MS Doc

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...