2016-01-17 173 views
0

現在我有這樣的:後臺運行服務器

[STAThread] 
static void Main() 
     { 
      if (flag) //client view 
       Application.Run(new Main_Menu()); 
      else 
      { 
       Application.Run(new ServerForm()); 
      } 
     } 

ServerForm.cs

public partial class ServerForm : Form 
    { 
     public ServerForm() 
     { 
      InitializeComponent(); 
      BeginListening(logBox); 
     } 

     public void addLog(string msg) 
     { 
      this.logBox.Items.Add(msg); 
     } 

     private void button1_Click(object sender, EventArgs e) 
     { 

     } 
     private async void BeginListening(ListBox lv) 
     { 
      Server s = new Server(lv); 
      s.Start(); 
     } 
    } 

Server.cs

public class Server 
    { 
     ManualResetEvent allDone = new ManualResetEvent(false); 
     ListBox logs; 
     /// 
     /// 
     /// Starts a server that listens to connections 
     /// 
     public Server(ListBox lb) 
     { 
      logs = lb; 
     } 
     public void Start() 
     { 
      Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
      listener.Bind(new IPEndPoint(IPAddress.Loopback, 1440)); 
      while (true) 
      { 
       Console.Out.WriteLine("Waiting for connection..."); 
       allDone.Reset(); 
       listener.Listen(100); 
       listener.BeginAccept(Accept, listener); 
       allDone.WaitOne(); //halts this thread 
      } 
     } 
     //other methods like Send, Receive etc. 
} 

我想運行我的ServerForm(它有ListBox可以從Server打印msg)。我知道ListBox參數不起作用,但我不能運行Server inifinite循環沒有掛起ServerForm(我甚至不能移動窗口)。我也嘗試過線程 - 不幸的是,它不適用於。

+0

表單是一個UI組件,不是應該在套接字上偵聽的東西。將服務器分成它自己的類,讓它報告它的狀態(例如通過事件)並將它託管在後臺工作者,任務或線程中。 – CodeCaster

+0

因此,如果我添加到我的'ServerForm' EvenListener和生成即使從'服務器'將'ServerForm'接收它? –

+0

使用背景工作。 – jdweng

回答

1

WinForms有一些稱爲UI線程的東西。它是一個負責繪製和處理UI的線程。如果該線程忙於做某事,UI將停止響應。

常規套接字方法阻塞。這意味着它們不會將控制權返回給您的應用程序,除非套接字上發生了什麼情況。因此,每次在UI線程上執行套接字操作時,UI都會停止響應,直到套接字方法完成。

爲了解決這個問題,您需要爲套接字操作創建一個單獨的線程。

public class Server 
{ 
    ManualResetEvent allDone = new ManualResetEvent(false); 
    Thread _socketThread; 
    ListBox logs; 

    public Server(ListBox lb) 
    { 
     logs = lb; 
    } 

    public void Start() 
    { 
     _socketThread = new Thread(SocketThreadFunc); 
     _socketThread.Start(); 
    } 

    public void SocketThreadFunc(object state) 
    { 
     Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
     listener.Bind(new IPEndPoint(IPAddress.Loopback, 1440)); 
     while (true) 
     { 
      Console.Out.WriteLine("Waiting for connection..."); 
      allDone.Reset(); 
      listener.Listen(100); 
      listener.BeginAccept(Accept, listener); 
      allDone.WaitOne(); //halts this thread 
     } 
    } 
    //other methods like Send, Receive etc. 
} 

但是,所有UI操作必須發生在UI線程上。這,如果你嘗試從套接字線程更新listbox,你將會得到一個異常。

解決該問題的最簡單方法是使用Invoke