2010-06-30 65 views
1

我正在運行四個線程獲取並設置相同的屬性。 當我使用斷點,然後它給我如預期的結果,但是當我直接運行它時,它給了我最後更新的結果。如何鎖定線程的setter屬性

這裏是我的代碼時執行的代碼是我在所有的消息框獲得8003

int Port { get; set; } 
Thread[] tMain= new Thread[4]; 

public void btnListen_Click(object sender, EventArgs e) 
     { 
      for (int i = 0; i < 4; i++) 
      { 
       tMain[i] = new Thread(Connect); 
       tMain[i].IsBackground = true; 
       tMain[i].Start(8000+i); 
      } 
     } 


public void Connect(object _port) 
     { 
      try 
      { 
       lock ((object)Port) 
       { 
        Port = (int)_port; 
       } 
       IPEndPoint ie = new IPEndPoint(IPAddress.Any, Port); 
       Socket listenSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
       listenSock.Bind(ie); 
       listenSock.Listen(100); 
       Thread tListen = new Thread(() => StartListening(listenSock, Port)); 
       tListen.IsBackground = true; 
       tListen.Start(); 
      } 
      catch (SocketException ex) 
      { 
       MessageBox.Show(ex.Message); 
      } 
     } 

public void StartListening(Socket _socket, int port) 
     { 
      Socket tempSock,listenerSocket=(Socket)_socket; 
      MessageBox.Show("Thread Started"+port.ToString()); 
      while (true) 
      { 
       MessageBox.Show("Waiting For Connection"); 
       tempSock = listenerSocket.Accept(); 

       Thread tInner = new Thread(ProcessMessages); 
       tInner.IsBackground = true; 
       tInner.Start(tempSock); 
      } 
     } 

現在我看到了這裏。這可能是因爲前3個線程在訪問時無法修改屬性。如何在這種情況下獲得鎖定。

+0

爲什麼你實際上需要「端口」屬性?這段代碼有很多問題,但我們首先需要該屬性。如果你只是刪除它和所有與之相關的代碼會怎麼樣?在調用IPEndPoint構造函數時,不要使用「Port」,只需傳遞'(int)_port'。這不會解決你所有的問題嗎? – 2010-06-30 07:59:48

+0

@Lasse:我以前只使用(int)_port,當它成功運行時,我用屬性替換它只是爲了做一些RND,並發現這個問題。這就是爲什麼。否則,我也有使用集合的想法。 – 2010-06-30 08:08:15

回答

2

這段代碼在開始時肯定需要一些重構 - 太多的線程正在跨越,並且都在一個非常狹窄的環境中!

簡短的回答:

的問題歸結爲一個事實,即Connect功能沒有在時間(甚至順序),你希望它是,而是隻有當循環結束後調用。

龍答:

這是併發問題相當典型的場景試圖函數內使用實例作用域變量/屬性時。據我所知,沒有得到期望值Port的問題與鎖定本身沒有直接關係。 (它可能以這種方式解決,但不是很優雅,也不會像你可能想到的那樣)。最終,你無法控制如何將時間塊分配給處理器級別的不同線程,因此你不知道哪些函數會被執行以什麼順序。你似乎也混合了有狀態和無狀態(功能)設計的原則,這必然會讓你陷入困境。堅持一個 - 在這種情況下最好是後者 - 而且你會獲得更多的成功。

所以,我希望我在這裏表示對於多線程讀起來可能是有益的 - 這是一個非常複雜的話題 - 並且實踐一些常見的原則。祝你好運!

+0

@Noldorin:沒有什麼比我感覺更苛刻。我很高興知道這些。雖然這是我第一個創建Socket和多線程的程序。正如你剛纔告訴的那樣,線程在循環終止後被調用,所以這是線程的一個新的隱藏功能。雖然我在這裏有2-3種解決方案可供使用。通過使用集合或使用端口的靜態值。還有什麼其他的事情可以做,如果我想鎖定那麼我將如何採取它。在這種情況下是否有可能獲得鎖定。因爲我認爲鎖定是不可能的 – 2010-06-30 08:12:59

+0

正如你所解釋的,每個線程都會在循環終止後啓動。 – 2010-06-30 08:13:20

+0

最明顯的解決方案可能只是爲了擺脫你的'Port'類變量 - 無論如何也不太清楚它的需要。在功能上做所有​​事情,並將事情作爲參數傳遞。 – Noldorin 2010-06-30 08:18:09