Поточная обработка только блокирует первый поток

У меня есть сценарий, где команда входит по сокету, который требует изрядного объема работы. Только один поток может обработать данные за один раз. Команды войдут быстрее, чем может обработать его. Со временем там будет тихо задний журнал.

Хорошая часть - то, что я могу отбросить потоки ожидания и действительно только иметь для обработки последнего, который ожидает - (или обработайте первый в и отбросьте все другие однажды). Я думал об использовании семафора управлять критическим разделом кода и использовать булевскую переменную, чтобы видеть, существует ли какое-либо блокирование потоков. Если бы там блокируют поток, я просто отбросил бы поток.

Мой ум терпит неудачу о том, как реализовать его приятно, я хотел бы реализовать его с использованием целого числа или булевской переменной, чтобы видеть, существует ли поток уже, ожидающий.

Я кодирую это в c#

1
задан John Soer 10 July 2010 в 05:08
поделиться

4 ответа

Вы можете использовать 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
ответ дан 2 September 2019 в 23:08
поделиться

Похоже, вам просто нужно использовать оператор lock . Код внутри оператора lock позволит только одному потоку работать внутри блока кода одновременно.

Дополнительная информация: Заявление о блокировке

0
ответ дан 2 September 2019 в 23:08
поделиться

Я полагаю, вы ищете оператор блокировки.

private readonly object _lock = new object();

private void ProccessCommand(Command command)
{
    lock (_lock)
    {
        // ...
    }
}
1
ответ дан 2 September 2019 в 23:08
поделиться

Судя по тому, что вы разместили здесь, вы могли бы избежать такого большого количества ожидающих потоков. Вы можете поставить в очередь следующую команду для выполнения и вместо того, чтобы заставлять потоки ждать, просто замените команду на выполнение следующей после завершения текущей команды. Блокировка при замене и снятии команды "ожидание".

Примерно так:

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

Это полезный класс потоковой передачи.

0
ответ дан 2 September 2019 в 23:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: