2013-05-08 2 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

Является ли это многозадачным приложением? –

+3

это треа ** d **, а не «угроза». – didierc

+0

Существует главный, а затем сервер, который должен запускать новый поток на фоне. – nabrugir

ответ

1

Это уже хорошо поддерживается TcpListener, используйте метод BeginAcceptTcpClient() вместо этого. Когда вы вызываете его из основного потока приложения WPF или Winforms, обратный вызов будет запускаться в том же главном потоке автоматически. То же самое относится к методу BeginReceive(). Внутри он использует цикл диспетчера, чтобы активировать метод обратного вызова, очень похожий на способ работы класса BackgroundWorker и C# v5 async/await.

Это избавляет вас от хлопот начального конца, заканчивающегося вашей собственной нитью, и обеспечения правильной работы маршала. И значительно сократить использование ресурсов вашей программой. Настоятельно рекомендуется.

+0

Вы хотите запустить TcpListener из WPF и не использовать класс TCPServer? или создать новый класс с помощью TCPListener? Любая ссылка или пример помогут. – nabrugir

0

Очередь - это ответ. В частности, в этом случае Concurrent Queue.

Ваша резьба сокета помещает сообщения в очередь. Ваш рабочий поток (ы) опросит очередь и вытащит рабочие элементы.

Для приложений на основе сокетов этот шаблон очень, очень распространен.

В качестве альтернативы вы можете использовать QueueUserWorkItem против пула системных потоков и позволить ему управлять рабочей нагрузкой.

Примечание: вы находитесь в многопоточной земле сейчас. Вам нужно будет прочитать о синхронизации и других проблемах, которые будут возникать. Невыполнение этого означает, что ваше приложение будет иметь очень странные ошибки.

Смежные вопросы