У меня есть сценарий, где команда входит по сокету, который требует изрядного объема работы. Только один поток может обработать данные за один раз. Команды войдут быстрее, чем может обработать его. Со временем там будет тихо задний журнал.
Хорошая часть - то, что я могу отбросить потоки ожидания и действительно только иметь для обработки последнего, который ожидает - (или обработайте первый в и отбросьте все другие однажды). Я думал об использовании семафора управлять критическим разделом кода и использовать булевскую переменную, чтобы видеть, существует ли какое-либо блокирование потоков. Если бы там блокируют поток, я просто отбросил бы поток.
Мой ум терпит неудачу о том, как реализовать его приятно, я хотел бы реализовать его с использованием целого числа или булевской переменной, чтобы видеть, существует ли поток уже, ожидающий.
Я кодирую это в c#
Вы можете использовать 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);
}
Похоже, вам просто нужно использовать оператор lock
. Код внутри оператора lock
позволит только одному потоку работать внутри блока кода одновременно.
Дополнительная информация: Заявление о блокировке
Я полагаю, вы ищете оператор блокировки.
private readonly object _lock = new object();
private void ProccessCommand(Command command)
{
lock (_lock)
{
// ...
}
}
Судя по тому, что вы разместили здесь, вы могли бы избежать такого большого количества ожидающих потоков. Вы можете поставить в очередь следующую команду для выполнения и вместо того, чтобы заставлять потоки ждать, просто замените команду на выполнение следующей после завершения текущей команды. Блокировка при замене и снятии команды "ожидание".
Примерно так:
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
Это полезный класс потоковой передачи.