2010-07-10 196 views
1

我有一個命令通過套接字進入需要相當數量的工作的場景。一次只能有一個線程處理數據。這些命令會比處理它快。隨着時間的推移,將有一個安靜的日誌。線程只阻塞第一個線程

好的部分是我可以放棄等待的線程,並且只需處理最後一個正在等待的線程(或者處理第一個線程並丟棄所有其他線程)。我正在考慮使用信號量來控制代碼的關鍵部分,並使用布爾值來查看是否有線程阻塞。如果有阻塞線程,我會放棄該線程。

我的想法是如何很好地實現它的空白我想實現它與out使用整數或布爾值來查看是否有一個線程已經等待。

我在c編碼這個#

回答

1

您可以使用Monitor.TryEnter看鎖是否已被佔用的對象上:

void ProcessConnection(TcpClient client) 
{ 
    bool lockTaken = false; 

    Monitor.TryEnter(lockObject, out lockTaken); 

    if (!lockTaken) 
    { 
     client.Close(); 
     return; 
    } 

    try 
    { 
     // long-running process here 
    } 
    finally 
    { 
     Monitor.Exit(lockObject); 
     client.Close(); 
    } 
} 

請注意,這個工作還是得要調用的方法在一個線程,例如:

client = listener.AcceptTcpClient(); 
ThreadPool.QueueUserWorkItem(notused => ProcessConnection(client)); 

僅供參考,lock語句是剛剛糖:

Monitor.Enter(lockObject); 

try 
{ 
    // code within lock { } 
} 
finally 
{ 
    Monitor.Exit(lockObject); 
} 
1

我相信你正在尋找鎖定語句。

private readonly object _lock = new object(); 

private void ProccessCommand(Command command) 
{ 
    lock (_lock) 
    { 
     // ... 
    } 
} 
+0

這將工作,以確保只有一個線程正在執行工作,但我只想要一個線程阻塞鎖。如果鎖上有線程阻塞,我想放棄該線程。 – 2010-07-10 05:18:21

0

這聽起來像你只需要使用lock聲明。 lock語句中的代碼將只允許一個線程一次在代碼塊內部工作。

更多信息:lock Statement

0

從你在這裏發佈的聲音中,你可能能夠避免這麼多的等待線程。您可以排隊執行下一個命令,而不是讓線程保持等待狀態,只需在當前命令結束後替換要執行的命令即可。更換和刪除「等待」命令時鎖定。

事情是這樣的:

class CommandHandler 
{ 
    Action nextCommand; 
    ManualResetEvent manualResetEvent = new ManualResetEvent(false); 
    object lockObject = new object(); 

    public CommandHandler() 
    { 
     new Thread(ProcessCommands).Start();      
    } 

    public void AddCommand(Action nextCommandToProcess) 
    { 
     lock (lockObject) 
     { 
      nextCommand = nextCommandToProcess; 
     } 
     manualResetEvent.Set(); 
    } 

    private void ProcessCommands() 
    { 
     while (true) 
     { 
      Action action = null; 
      lock (lockObject) 
      { 
       action = nextCommand; 
       nextCommand = null; 
      } 
      if (action != null) 
      { 
       action(); 
      } 
      lock (lockObject) 
      { 
       if(nextCommand != null) 
        continue; 
       manualResetEvent.Reset(); 
      } 

      manualResetEvent.WaitOne(); 
     } 
    } 
} 

退房:ManualResetEvent

這是一個有用的線程類。