2009-11-17 119 views
1

我有以下幾點:線程和套接字

ThreadStart startThread = 
    delegate 
    { 
      mySocket.StartListen(); 
    }; 

mySocket現在循環在聽()的時候我:

new Thread(startThread).Start(); 

這裏是StartListen:

public void StartListen() 
{ 
Object locker = new Object(); 

// Lock resources 
lock (locker) 
{ 
    S = new System.Net.Sockets.Socket(System.Net.Sockets.AddressFamily.InterNetwork, 
     System.Net.Sockets.SocketType.Stream, 
     System.Net.Sockets.ProtocolType.Tcp); 
    S.Blocking = false; 

    try 
    { 
    S.Bind(serverEP); 
    S.Listen(1000); 
    isListening = true; 

    /* 
    * While statement not required here because AcceptConnection() 
    * method instructs the socket to BeginAccept() again... 
    */ 
    //while (true) 
    //{ 
    connectDone.Reset(); 
    S.BeginAccept(new AsyncCallback(AcceptConnection), Channel); 
    connectDone.WaitOne(); 
    //} 
    } 
    catch (System.Net.Sockets.SocketException SockEx) 
    { 
    Console.WriteLine("*****[" + name + "] " + SockEx.SocketErrorCode + ":"); 
    Console.WriteLine("*****[" + name + "] " + SockEx.Message); 
    } 
} 
} 

由於異步方法並不真正「完成」並返回一個信號用於其他任何事情繼續。在上面的Thread.Start()之後實現的任何命令都無法正常工作。例如,在StartListen中,請注意我有一個isListening = true。在我啓動線程後,我想使用屬性IsListening。它總是被返回爲假。

我應該如何開始線程。異步方法(即ThreadStart.BeginInvoke())是否可以選擇?是不是很類似於使用ManualResetEvent?

回答

2

Mark isListening as volatile。據我所知,你在兩個不同的線程中引用這個標誌。通常,線程之間共享的數據必須同步,但不會出現這種情況。但是,鑑於該標誌是一個布爾類型,你沒有技術上必須同步訪問它,因爲.NET框架保證讀取和寫入布爾類型是原子的(我認爲我說的是正確的..有人請糾正我,如果它不是技術上正確的)。但是,爲了確保從該類型讀取實際上獲得最新值,您需要將其標記爲volatile

此外,您最好使用TcpListener類,而不是嘗試使用Socket類來做到這一點。你所做的沒有錯,但TcpListener類會使你的代碼更易於讀取和維護IMO。

最後,您使用的locker對象實際上並沒有做任何事情,因爲它在StartListen()方法中是本地的。爲了讓同步對象產生任何效果,需要可以訪問需要序列化訪問共享數據的線程。你在這裏做的方式,其他線程不能訪問變量,因此使其無用。

+0

我以前沒有用過'volatile'。我會閱讀它。使用TcpListener並不完全沒有問題。但是,我已經完成了編寫和使用Sockets類的所有異步操作。我選擇使用基類而不是簡單地在TcpListener/TcpClient上進行操作。 :) – IAbstract 2009-11-17 18:11:56

+0

使用'Socket'類沒有錯。只是'TcpListener'更容易,因爲它是專門爲你如何使用'Socket'而設計的。 – 2009-11-17 18:29:23