I am writing in Borland C ++ Builder 6. I need to understand the threads, I decided to start with a simple task that works without threads. But even in a simple stalled. Task: there is a server and a client (camp and laptop, connected by Ethernet cable), to the server, data is being transmitted over the UDP protocol using WinSock. Everything works even with threads but strange. I understand that if you register

ThreadUDPServer *thr; thr = new ThreadUDPServer(false); 
That goes the start of the stream and the transfer of control to the Execute () method. But this does not happen, control passes to the flow designer, and since there is nothing there, it returns to the form flow. Even Resume () does not help.

 thr->Resume(); 

With the help of Breakpoint it was found out that the control to the Execute () method is transferred only when the code of the form stream completes.

Here is my code, it is possible that I did not understand something and wrote wrong:

Unit1.h *

 //--------------------------------------------------------------------------- #ifndef Unit1H #define Unit1H #include "Unit2.h" //--------------------------------------------------------------------------- #include <Classes.hpp> #include <Controls.hpp> #include <StdCtrls.hpp> #include <Forms.hpp> //--------------------------------------------------------------------------- class TForm1 : public TForm { __published: // IDE-managed Components TEdit *Edit1; TEdit *Edit2; private: // User declarations public: // User declarations ThreadUDPServer *thr; __fastcall TForm1(TComponent* Owner); }; //--------------------------------------------------------------------------- extern PACKAGE TForm1 *Form1; //--------------------------------------------------------------------------- #endif 

* Unit1.cpp

 //--------------------------------------------------------------------------- #include <vcl.h> #pragma hdrstop #include "Unit1.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { thr = new ThreadUDPServer(false); // создаем поток в приостановленном состоянии (true), запущенном (false) //thr->Resume(); // запустить поток выполняться Edit1->Text = thr->buf[0]; Edit2->Text = thr->buf[1]; } //--------------------------------------------------------------------------- 

Unit2.h

 //--------------------------------------------------------------------------- #ifndef Unit2H #define Unit2H //--------------------------------------------------------------------------- #include <Classes.hpp> #include "winsock2.h" //--------------------------------------------------------------------------- class ThreadUDPServer : public TThread { private: protected: void __fastcall Execute(); public: char buf[20]; __fastcall ThreadUDPServer(bool CreateSuspended); }; //--------------------------------------------------------------------------- #endif 

Unit2.cpp

 //--------------------------------------------------------------------------- #include <vcl.h> #pragma hdrstop #include "Unit1.h" #include "Unit2.h" #pragma package(smart_init) //--------------------------------------------------------------------------- // Important: Methods and properties of objects in VCL can only be // used in a method called using Synchronize, for example: // // Synchronize(UpdateCaption); // // where UpdateCaption could look like: // // void __fastcall ThreadUDPServer::UpdateCaption() // { // Form1->Caption = "Updated in a thread"; // } //--------------------------------------------------------------------------- __fastcall ThreadUDPServer::ThreadUDPServer(bool CreateSuspended) : TThread(CreateSuspended) { } //--------------------------------------------------------------------------- void __fastcall ThreadUDPServer::Execute() { FreeOnTerminate = true; // освободить занятую потоком память по окончании его работы const int iReqWinsockVer = 2; WSADATA wsaData; if (WSAStartup(iReqWinsockVer,&wsaData)==0) { ShowMessage("Инициализация библиотеки сокета(Ws2_32.dll) удалась"); SOCKET s; s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (s == INVALID_SOCKET) ShowMessage("При создании сокета возникла ошибка: " + WSAGetLastError()); else ShowMessage("Создание сокета было успешным!"); sockaddr_in sockAddr; sockAddr.sin_family = AF_INET; sockAddr.sin_port = htons(80); sockAddr.sin_addr.S_un.S_addr = INADDR_ANY; if (bind(s, (sockaddr*)(&sockAddr), sizeof(sockAddr))!=0) ShowMessage("Связывание адреса с socket'ом не произошло"); else ShowMessage("Связывание адреса с socket'ом было успешным!"); buf[0] = '1'; ShowMessage(buf[0]); while(true) { sockaddr_in client_addr; int iSize = sizeof(client_addr); int ret = recvfrom(s, buf, sizeof(buf), 0, (struct sockaddr *)&client_addr, &iSize); if (ret != 0) { ShowMessage("Данные были полученны успешно!"); ShowMessage(buf[0]); ShowMessage(buf[1]); break; } else ShowMessage("При получении данных возникла ошибка"); } closesocket(s); if (WSACleanup() == 0) ShowMessage("Освобождение ресурсов WinSock завершилось успехом"); else ShowMessage("Освобождение ресурсов WinSock не удалось"); } else ShowMessage("Инициализация библиотеки сокета(Ws2_32.dll) не удалась"); } //--------------------------------------------------------------------------- 

    1 answer 1

    I would not begin to form a stream in the form constructor or in OnFormCreate. Try with a button. Although perhaps I am wrong. But I always ran the stream from the already final form.

    • Yes, most likely, you are right. But how to organize everything so that the stream receives data through sockets, and the form at this time displayed the result in Edit1 and Edit2. This is not my understanding how to do all this? - WFZ
    • Paste the appropriate #include "Form1.h" into the stream file. And in Execute (), and produce everything. The stream file will know about your Edits - BuilderC