2016-01-17 174 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