2013-05-08 77 views
0

我正在主應用程序運行一個C#服務器,我想將從服務器線程收到的消息傳遞給主線程。服務器應該在後臺運行以獲得新的連接。每次有新連接時,服務器都應該將收到的消息傳遞給主應用程序。如何讓主應用知道何時收到消息?當有新連接時,如何將消息從服​​務器線程傳遞到主線程?從後臺線程發送數據到主線程

主要應用

public partial class MainWindow : Window 
{ 
     TCPServer Server = new TCPServer(); //start running the server 
     //get the message (Server.message) when a client sent it to the server 
     //TODO process the message 
    } 

TCP服務器

class TCPServer 
    { 
     private TcpListener tcpListener; 
     private Thread listenThread; 
     private String message; 

     public TCPServer() 
    { 
     this.tcpListener = new TcpListener(IPAddress.Any, 3200); 
     this.listenThread = new Thread(new ThreadStart(ListenForClients)); 
     this.listenThread.Start(); 

    } 

//starts the tcp listener and accept connections 
    private void ListenForClients() 
    { 
     this.tcpListener.Start(); 

     while (true) 
     { 
      //blocks until a client has connected to the server 
      System.Diagnostics.Debug.WriteLine("Listening..."); 
      TcpClient client = this.tcpListener.AcceptTcpClient(); 
      System.Diagnostics.Debug.WriteLine("Client connected"); 


      //create a thread to handle communication 
      //with connected client 
      Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm)); 
      clientThread.Start(client); 
     } 
    } 


    //Read the data from the client 
    private void HandleClientComm(object client) 
    { 

     TcpClient tcpClient = (TcpClient)client; //start the client 
     NetworkStream clientStream = tcpClient.GetStream(); //get the stream of data for network access 

     byte[] message = new byte[4096]; 
     int bytesRead; 

     while (true) 
     { 
      bytesRead = 0; 

      try 
      { 
       //blocks until a client sends a message 
       bytesRead = clientStream.Read(message, 0, 4096); 
      } 
      catch 
      { 
       //a socket error has occured 
       break; 
      } 

      if (bytesRead == 0) //if we receive 0 bytes 
      { 
       //the client has disconnected from the server 


      break; 
       } 
       //message has successfully been received 
       ASCIIEncoding encoder = new ASCIIEncoding(); 
       message = encoder.GetString(message, 0, bytesRead); 

       //Reply 
       byte[] buffer = encoder.GetBytes("ACK"); 
       clientStream.Write(buffer, 0, buffer.Length); 
       System.Diagnostics.Debug.WriteLine("ACK"); 
       clientStream.Flush(); 
       } 
      tcpClient.Close(); 
      System.Diagnostics.Debug.WriteLine("Client disconnected"); 
     } 
+3

這是一個多處理器的應用程序嗎? – 2013-05-08 23:21:03

+3

這是威脅**,而不是「威脅」。 – didierc 2013-05-08 23:23:45

+0

有主服務器,然後服務器應該在後臺運行新線程。 – nabrugir 2013-05-08 23:35:43

回答

1

這是已經很好地支持的TcpListener,使用BeginAcceptTcpClient()方法來代替。當你從WPF或Winforms應用程序的主線程調用它時,回調將自動在同一主線程上運行。這同樣適用於它的BeginReceive()方法。在內部,它使用調度程序循環來獲取激活的回調方法,這與BackgroundWorker和C#v5 async/await關鍵字類的工作方式非常相似。

這可以讓您免受起始終止麻煩,終止您自己的線程並確保您的編組正確回退。並大大減少您的程序的資源使用情況。強烈推薦。

+0

你的意思是從WPF運行TcpListener並避免使用TCPServer類?或者用TCPListener創建一個新類?任何參考或示例都會有所幫助。 – nabrugir 2013-05-09 00:00:17

0

隊列就是答案。具體在這種情況下,一個Concurrent Queue

您的套接字線程將消息放入隊列中。您的工作線程輪詢隊列並取出工作項目。

對於基於套接字的應用程序,這種模式非常非常常見。

或者,您可以針對系統線程池QueueUserWorkItem,並讓它管理工作負載。

注意:您現在處於多線程狀態。你需要閱讀關於同步和其他將出現的問題。不這樣做意味着你的應用程序將有非常奇怪的錯誤。