从其他线程调用Form方法(调用)

时间:2018-06-27 20:31:13

标签: multithreading winforms c++-cli invoke

我在主线程上运行了WinForm,在单独的线程上运行了while(true)循环。该while(true)的每个循环都会创建一个新的System::String^,我想将该String粘贴到我的UI上的TextBox中。

我的文件结构包括GUI.hGUI.cppOther.cpp

GUI.h包含主要(也是唯一)表单的所有自动创建的代码。它还有一些GetSetButtonClick方法。

//GUI.h
#pragma once

#include <string>
#include <vector>
#include <cliext\vector>
#include <conio.h>
#include <list>
#include <iostream>

extern void BufferRecieveLoop();

namespace GUI_Example_Receive { 

    static bool loopFlag = true;

    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;

    /// <summary>
    /// Summary for GUI
    /// </summary>
    public ref class GUI : public System::Windows::Forms::Form
    {
    public:
        GUI(void)
        {
            InitializeComponent();
        }
        std::vector<std::string> CollectText();
        void ContinueNormally(); // Object^);
        void DisableAllTextboxes();
        void EnableAllTextboxes();

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

    private:
        //Labels
        //GroupBoxes
        //Buttons
        //SaveFile

    public:
        //TextBoxes
        System::Windows::Forms::TextBox^  consoleTextBox;

    private:
        System::ComponentModel::Container ^components;

#pragma region Windows Form Designer generated code
        void InitializeComponent(void)
        {
            //automatically made, lightly edited
        }
#pragma endregion

    public: 
        void SetConsoleTextBoxText(System::String^ input)
        {
            this->consoleTextBox->Text = input;
            this->consoleTextBox->Refresh();
        }

        void ClearConsoleTextBoxText()
        {
            this->consoleTextBox->Clear();
        }

        delegate void MyDelegate(System::String ^ str);

        void ClearAndSetConsoleTextBoxText(System::String ^ input)
        {
            /***************************************************
            if (InvokeRequired)
            {
                this->BeginInvoke(gcnew MyDelegate(this, &ClearAndSetConsoleTextBoxText), { input });
            }
            ***************************************************/
            ClearConsoleTextBoxText();
            SetConsoleTextBoxText(input);
        }

        System::Void startButton_Click(System::Object^  sender, System::EventArgs^  e)
        {
            loopFlag = true; //able to loop through ContinueNormally()

            ContinueNormally(); //method in GUI.cpp
        }

    };

    //https://social.msdn.microsoft.com/Forums/vstudio/en-US/4da834f0-d8f8-4abb-a655-ef9e99d51eb2/how-to-create-a-global-object-of-a-ref-class-type?forum=vcgeneral
    ref struct Globals {
        static GUI ^gui; //using Globals::gui everywhere to access the one Form
    };

}

Gui.cpp包含用于Run()表单,启动线程并永久循环的代码。

//GUI.cpp
void BufferRecieveLoop()
{
    while (true)
    {
        size_t bytes_read = multicast.Receive(buffer, Example::MTU_SIZE);

        incoming.Process(buffer, bytes_read, endian); //method in Other.cpp
    }
}

void GUI::ContinueNormally()
{
    System::Threading::Thread ^loopThread = gcnew System::Threading::Thread(gcnew System::Threading::ThreadStart(BufferRecieveLoop));
    loopThread->Start();
    loopThread->Join();
}

static void Start()
{
    Globals::gui = gcnew GUI;
    System::Windows::Forms::Application::Run(Globals::gui);
}

int __cdecl main(int argc, char* argv[])
{
    System::Windows::Forms::Application::EnableVisualStyles();
    System::Windows::Forms::Application::SetCompatibleTextRenderingDefault(false);

    Start();

    return 0;
}

Other.cpp创建一个String^并调用GUI.h中的方法来更改文本框中的文本。

//Other.cpp
void Process(const DIS::Pdu& packet)
{
    System::String^ sysStr2 = "stuff";

    GUI_Example_Receive::Globals::gui->ClearAndSetConsoleTextBoxText(sysStr2);

    //GUI_Example_Receive::Globals::gui->BeginInvoke(gcnew MyStringDelegate(GUI_Example_Receive::Globals::gui, &GUI_Example_Receive::GUI::ClearAndSetConsoleTextBoxText), { sysStr2 });
}

我不知道在哪里正确Invoke我的方法。我也不知道如何{em>如何 Invoke我的方法。我发现的很多东西都是C#,但对我却没有用。

我是从Other.cpp还是在GUI.h中被调用的方法内部调用?

1 个答案:

答案 0 :(得分:0)

万一将来有其他人对此有疑问,并且像我一样,找不到很多c ++代码示例,我将发布解决方案。

在我的SetConsoleTextBoxText()文件中,我有一个consoleTextBox方法。这仅可用于拥有Invoke()的线程。因此,尝试调用该方法的任何其他线程都需要//GUI.h delegate void MyDelegate(System::String ^ text); void SetConsoleTextBoxText(System::String^ input) { if (this->consoleTextBox->InvokeRequired) //is a thread other than the owner trying to access? { MyDelegate^ myD = gcnew MyDelegate(this, &GUI::SetConsoleTextBoxText); //GUI is the ref class. Replace with wherever your function is located. this->Invoke(myD, gcnew array<Object^> { input }); //Invoke the method recursively } else { //Normal function of this method. This will be hit after a recursive call or from the owning thread this->consoleTextBox->Text = input; this->consoleTextBox->Refresh(); } } 方法(将控制权交还给拥有的线程)。

availabilityResults
| where timestamp > ago(1d)
| summarize avg(duration) by bin(timestamp, 10m), name
| render timechart 
相关问题