Есть ли способ сделать асинхронные потоки / функции при использовании форм .NET c ++ / cli? - PullRequest
2 голосов
/ 21 октября 2019

Я новичок в программировании, поэтому, если в моем коде есть какая-то нелепая ошибка или плохие идеи, дайте мне знать. :)

Я создал пустой проект CLR в Visual Studio, чтобы попытаться добавить графический интерфейс к клиенту программы обмена сообщениями, которую я написал на c ++.

Клиент интерфейса работает нормально, но этомогу только отправлять сообщения, потому что я не мог найти способ перевести способ, которым я закодировал в клиенте консоли к интерфейсу. В консольном клиенте я использовал библиотеку <future> для создания асинхронного потока, чтобы он мог продолжать проверять наличие новых сообщений от сервера.

Примерно так:

future<void> f1 = async(launch::async, newMsg, sock);
void newMsg(SOCKET sock) 
{
    while (true)
    {
        char buffer[512];
        ZeroMemory(buffer, 512);
        int byteRecived = recv(sock, buffer, 512, 0);
        if (byteRecived > 0)
        {
            cout << string(buffer, 0, byteRecived) << endl;
        }
    }
}

Но при компиляции с clr <future> не поддерживается. Можно ли как-нибудь заставить программу всегда проверять наличие сообщений, а также отправлять сообщения?

Я использую winsock tcp / ip для подключения клиент-сервер.

JanelaPrincipal.h

#include <Windows.h>
#include "iostream"
#include "winsock2.h"
#include "WS2tcpip.h"
#include "string"
#include "locale.h"
#include <msclr\marshal_cppstd.h>

#pragma comment(lib, "ws2_32.lib")
#pragma once

namespace FakeWpp {

    using namespace System;
    using namespace System::ComponentModel;
    using namespace System::Collections;
    using namespace System::Windows::Forms;
    using namespace System::Data;
    using namespace System::Drawing;

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

    protected:
        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        ~JanelaPrincipal()
        {
            if (components)
            {
                delete components;
            }
        }
    private: System::Windows::Forms::Button^ buttonEnviar;
    protected:

    private: System::Windows::Forms::TextBox^ textBoxEnviar;
    private: System::Windows::Forms::TextBox^ textBoxReceber;

    private: System::Windows::Forms::Button^ buttonConectar;

    protected:

    private:
        /// <summary>
        /// Required designer variable.
        /// </summary>
        System::ComponentModel::Container ^components;

#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)
        {
            this->buttonEnviar = (gcnew System::Windows::Forms::Button());
            this->textBoxEnviar = (gcnew System::Windows::Forms::TextBox());
            this->textBoxReceber = (gcnew System::Windows::Forms::TextBox());
            this->buttonConectar = (gcnew System::Windows::Forms::Button());
            this->SuspendLayout();
            // 
            // buttonEnviar
            // 
            this->buttonEnviar->Location = System::Drawing::Point(197, 226);
            this->buttonEnviar->Name = L"buttonEnviar";
            this->buttonEnviar->Size = System::Drawing::Size(75, 23);
            this->buttonEnviar->TabIndex = 0;
            this->buttonEnviar->Text = L"Enviar";
            this->buttonEnviar->UseVisualStyleBackColor = true;
            this->buttonEnviar->Click += gcnew System::EventHandler(this, &JanelaPrincipal::buttonEnviar_Click);
            // 
            // textBoxEnviar
            // 
            this->textBoxEnviar->Location = System::Drawing::Point(12, 229);
            this->textBoxEnviar->Multiline = true;
            this->textBoxEnviar->Name = L"textBoxEnviar";
            this->textBoxEnviar->Size = System::Drawing::Size(179, 20);
            this->textBoxEnviar->TabIndex = 1;
            this->textBoxEnviar->KeyDown += gcnew System::Windows::Forms::KeyEventHandler(this, &JanelaPrincipal::textBoxEnviar_KeyDown);
            // 
            // textBoxReceber
            // 
            this->textBoxReceber->Location = System::Drawing::Point(12, 12);
            this->textBoxReceber->Multiline = true;
            this->textBoxReceber->Name = L"textBoxReceber";
            this->textBoxReceber->ReadOnly = true;
            this->textBoxReceber->ScrollBars = System::Windows::Forms::ScrollBars::Horizontal;
            this->textBoxReceber->Size = System::Drawing::Size(179, 208);
            this->textBoxReceber->TabIndex = 2;
            // 
            // buttonConectar
            // 
            this->buttonConectar->Location = System::Drawing::Point(197, 12);
            this->buttonConectar->Name = L"buttonConectar";
            this->buttonConectar->Size = System::Drawing::Size(75, 23);
            this->buttonConectar->TabIndex = 3;
            this->buttonConectar->Text = L"Conectar!";
            this->buttonConectar->UseVisualStyleBackColor = true;
            this->buttonConectar->Click += gcnew System::EventHandler(this, &JanelaPrincipal::buttonConectar_Click);
            // 
            // JanelaPrincipal
            // 
            this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
            this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
            this->ClientSize = System::Drawing::Size(284, 261);
            this->Controls->Add(this->buttonConectar);
            this->Controls->Add(this->textBoxReceber);
            this->Controls->Add(this->textBoxEnviar);
            this->Controls->Add(this->buttonEnviar);
            this->Name = L"JanelaPrincipal";
            this->Text = L"JanelaPrincipal";
            this->ResumeLayout(false);
            this->PerformLayout();

        }
#pragma endregion
    private: System::Void buttonEnviar_Click(System::Object^ sender, System::EventArgs^ e) {
        String^ userInputSys = textBoxEnviar->Text;
        std::string userInput = msclr::interop::marshal_as<std::string>(userInputSys);
            if (userInput.size() > 0)
            {
                int sendResult = send(sock, userInput.c_str(), userInput.size() + 1, 0);
                if (sendResult == SOCKET_ERROR)
                {
                    textBoxReceber->Text = textBoxReceber->Text + "A mensagem não foi enviada!\r\n";
                }
                else
                {
                    textBoxReceber->Text = textBoxReceber->Text + "Você: " + userInputSys + "\r\n";
                }
            }
            textBoxEnviar->Text = "";

    }
    public: System::Void buttonConectar_Click(System::Object^ sender, System::EventArgs^ e) {
        WSADATA data;
        int r = WSAStartup(MAKEWORD(2, 2), &data);
        if (r != 0)
        {
            textBoxReceber->Text = textBoxReceber->Text + "Falha Ao Iniciar Winsock!\r\n";
        }
        else
        {
            textBoxReceber->Text = textBoxReceber->Text + "Sucesso Ao Iniciar Winsock!\r\n";
        }

        sock = socket(AF_INET, SOCK_STREAM, 0);
        if (sock == INVALID_SOCKET)
        {
            textBoxReceber->Text = textBoxReceber->Text + "Falha ao criar o socket!\r\n";
            WSACleanup();
        }
        else
            textBoxReceber->Text = textBoxReceber->Text + "Sucesso! (socket)\r\n";

        sockaddr_in hint;
        hint.sin_family = AF_INET;
        hint.sin_port = htons(9000);
        inet_pton(AF_INET, "127.0.0.1", &hint.sin_addr);
        textBoxReceber->Text = textBoxReceber->Text + "Tentando conectar-se...\r\n";
        int connectionresult = connect(sock, (sockaddr*)&hint, sizeof(hint));
        if (connectionresult == SOCKET_ERROR)
        {
            textBoxReceber->Text = textBoxReceber->Text + "Não foi possível conectar ao servidor!\r\n";
            closesocket(sock);
            WSACleanup();
        }
        else
        {
            textBoxReceber->Text = textBoxReceber->Text + "Conectado com Sucesso!\r\n";
        }
    }

private: System::Void textBoxEnviar_KeyDown(System::Object^ sender, System::Windows::Forms::KeyEventArgs^ e) {

    if (e->KeyCode == Keys::Enter) {
        buttonEnviar_Click(this, gcnew EventArgs());
    }
}

};
}

JanelaPrincipal.cpp

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include "iostream"
#include "windows.h"
#include "JanelaPrincipal.h"

using namespace System;
using namespace System::Windows::Forms;
[STAThread]

void main()
{
    Application::EnableVisualStyles();
    Application::SetCompatibleTextRenderingDefault(false);
    FakeWpp::JanelaPrincipal form;
    Application::Run(% form);
}

Я просто хочу, чтобы клиент мог отправлять и получать сообщения

...