2012-01-11 67 views
1

我正在製作一個使用線程的窗體應用程序,這些線程正在運行並且可以工作,但是我希望我的線程可以訪問窗體組件。 像BtnMain這是線程函數內部看不到的。 我怎麼能解決這個?,這裏是我的代碼中使用託管C時我的線程沒有看到窗體窗體組件

#pragma once 

namespace winAppSocket { 
struct struttura{ 
char c; 
int num; 
} mystruct; 

UINT ServerThread(LPVOID pParam) 
{ 
printf("Starting up TCP server\r\n"); 
SOCKET server; 
WSADATA wsaData; 
sockaddr_in local; 
int wsaret=WSAStartup(0x101,&wsaData); 
if(wsaret!=0) 
{ 
    return 0; 
} 
local.sin_family=AF_INET; 
local.sin_addr.S_un.S_addr=INADDR_ANY; 
local.sin_port=htons((u_short)20248); 
server=socket(AF_INET,SOCK_STREAM,0); 
if(server==INVALID_SOCKET) 
{ 
    return 0; 
} 
if(bind(server,(sockaddr*)&local,sizeof(local))!=0) 
{ 
    return 0; 
} 
if(listen(server,10)!=0) 
{ 
    return 0; 
} 
SOCKET client; 
sockaddr_in from; 
int fromlen=sizeof(from); 
int buffer; 
char buff; 
while(true) 
{ 
    client=accept(server,(struct sockaddr*)&from,&fromlen); 
    //printf("pppp\n"); 
    //con la struct 
    int numByte=recv(client,(char*) &mystruct, (int) sizeof(mystruct), 0); 

    //printf("%c\t%d\n", mystruct.c, mystruct.num); 
    //ricevere un char funziona 
    //int numByte=recv(client, &buff, (int) sizeof(buff), 0); 
    //printf("%c\t%d\n", buff, numByte); 
    //int numByte=recv(client, buffer, (int) strlen(buffer), 0); 
    //questo funziona 
    //int numByte=recv(client, (char*)&buffer, (int) sizeof(buffer), 0); 
    //printf("%d\t%d\n", buffer, numByte); 
    //printf("Connection from %s\n", inet_ntoa(from.sin_addr)); 
    closesocket(client); 

} 
closesocket(server); 
WSACleanup(); 
return 0; 
} 

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 Form1 
/// 
/// WARNING: If you change the name of this class, you will need to change the 
///   'Resource File Name' property for the managed resource compiler tool 
///   associated with all .resx files this class depends on. Otherwise, 
///   the designers will not be able to interact properly with localized 
///   resources associated with this form. 
/// </summary> 
public ref class Form1 : public System::Windows::Forms::Form 
{ 
public: 
    Form1(void) 
    { 
     InitializeComponent(); 
     // 
     //TODO: Add the constructor code here 
     // 
    } 

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

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->BtnMain = (gcnew System::Windows::Forms::Button()); 
     this->SuspendLayout(); 
     // 
     // BtnMain 
     // 
     this->BtnMain->Location = System::Drawing::Point(139, 21); 
     this->BtnMain->Name = L"BtnMain"; 
     this->BtnMain->Size = System::Drawing::Size(120, 36); 
     this->BtnMain->TabIndex = 0; 
     this->BtnMain->Text = L"Start Main"; 
     this->BtnMain->UseVisualStyleBackColor = true; 
     this->BtnMain->Click += gcnew System::EventHandler(this, &Form1::BtnMain_Click); 
     // 
     // Form1 
     // 
     this->AutoScaleDimensions = System::Drawing::SizeF(6, 13); 
     this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font; 
     this->ClientSize = System::Drawing::Size(284, 262); 
     this->Controls->Add(this->BtnMain); 
     this->Name = L"Form1"; 
     this->Text = L"Package Analyzer"; 
     this->ResumeLayout(false); 

    } 

#pragma endregion 
private: System::Void BtnMain_Click(System::Object^ sender, System::EventArgs^ e) { 
AfxBeginThread(ServerThread,0); 
//while(_getch()!=27); 
} 
}; 
} 
+1

您*應該*只能在UI線程上與UI進行交互。但是,如果您絕對必須使用'Control.Invoke'方法在後臺線程上執行此操作。我建議使用類似於'BackgroundWorker'組件的東西,這有助於自動執行此操作。 – 2012-01-11 07:52:40

回答

2

你爲什麼不使用.NET線程++?讓事情變得更容易......但是,當您從不同線程訪問控件時,您將會遇到異常 - 您必須使用Invoke來更新線程中的控件。

編輯
好了,我只能寫C#,但我敢肯定,你可以很容易地將它轉換到C++:

private void BtnMain_Click(object sender, EventArgs e) 
{ 
    Thread t = new Thread(new ThreadStart(ThreadMethod)); 
    t.Start(); 
} 

private void ThreadMethod(object state) 
{ 
    // state would be set if you used ParameterizedThreadStart and t.Start(...) above 


    // DO YOUR STUFF HERE 
    ... 

    // Set text of label on form. You must use this.Invoke, as otherwise 
    // you'll run into an exception for changing controls from a different thread 
    this.Invoke((Action)delegate() 
    { 
     label1.Text = "Hello"; 
    }); 
} 

但它甚至沒有要求這樣做,你的情況 - 使用.NET TCP類!

您應該避免混合管理與非託管代碼,而是學習使用框架的能力。

+0

是的,這是一個很好的觀點。我完全錯過了對發佈代碼底部的'AfxBeginThread'的調用。我不知道你爲什麼將MFC和.NET結合起來。 – 2012-01-11 08:05:59

+0

我正在開發一個控制檯應用程序,現在我需要使它成爲Windows窗體應用程序。這就是我使用MFC的原因。你能告訴我如何在我的情況下使用.NET線程或後臺工作的代碼示例嗎?我想在單擊BtnMain之後啓動線程,並且想要例如更改Form1中標籤的文本 – andrea 2012-01-11 08:16:16

+0

編輯了我的答案。 – 2012-01-11 08:37:17