Что такое альтернатива WaitNamedPipe для ввода-вывода? - PullRequest
6 голосов
/ 26 марта 2012

Функция WaitNamedPipe позволяет клиентскому приложению канала синхронно ожидать доступное соединение на именованном канальном сервере.Затем вы вызываете CreateFile, чтобы открыть канал как клиент.Псевдокод:

// loop works around race condition with WaitNamedPipe and CreateFile
HANDLE hPipe;
while (true) {
    if (WaitNamedPipe says connection is ready) {
        hPipe = CreateFile(...);
        if (hPipe ok or last error is NOT pipe busy) {
            break; // hPipe is valid or last error is set
        }
    } else {
        break; // WaitNamedPipe failed
    }
}

Проблема в том, что это все блокирующие синхронные вызовы.Какой хороший способ сделать это асинхронно?Я не могу найти API, который использует перекрывающийся ввод / вывод, например, для этого.Например, для pipe server функция ConnectNamedPipe предоставляет параметры lpOverlapped, позволяющие серверу асинхронно ожидать клиента.Канальный сервер может затем вызвать WaitForMultipleObjects и дождаться завершения операции ввода-вывода или любого другого события (например, события, сигнализирующего потоку об отмене ожидающего ввода-вывода и завершении).

Единственный способ, которым я могу придумать, - это вызвать WaitNamedPipe в цикле с коротким, конечным тайм-аутом и проверить другие сигналы, если он истек.В качестве альтернативы, при циклическом вызове CreateFile проверьте другие сигналы, а затем вызовите Sleep с небольшой задержкой (или WaitNamedPipe).Например:

HANDLE hPipe;
while (true) {
    hPipe = CreateFile(...);
    if (hPipe not valid and pipe is busy) {
        // sleep 100 milliseconds; alternatively, call WaitNamedPipe with timeout
        Sleep(100);
        // TODO: check other signals here to see if we should abort I/O
    } else
        break;
}

Но этот метод, на мой взгляд, воняет на небеса.Если канал некоторое время недоступен, поток продолжает работать - он загружает процессор, использует электроэнергию, требует, чтобы страницы памяти оставались в оперативной памяти, и т. Д. На мой взгляд, поток, использующий Sleep или короткие тайм-ауты, неработать хорошо и является признаком небрежного многопоточного программирования.

Но какова альтернатива в этом случае?

Ответы [ 2 ]

5 голосов
/ 31 марта 2012

WaitNamedPipe абсолютно бесполезен и будет использовать весь процессор, если вы укажете тайм-аут, и сервер его не ждет.

Просто звоните CreateFile снова и снова с Sleep, каквы делаете, и переместите его в другие темы, как вы считаете целесообразным.Альтернативы API не существует.

Единственное «преимущество», предоставляемое WaitNamedPipe, заключается в том, что вы хотите знать, можете ли вы подключиться к именованному каналу, но вы явно не хотите фактически открывать соединение.Это мусор.

Если вы действительно хотите быть тщательным, ваши единственные варианты:

  • Убедитесь, что любая программа, открывающая именованный канал, всегда вызывает CreateNamedPipe снова сразу после его имениpipe подключен к.
  • Пусть ваша программа действительно проверит, запущена ли эта программа.
  • Если вы действительно не хотите иметь дополнительные подключения, все равно вызовите CreateNamedPipe, и когда кто-то подключится,скажите им, чтобы они ушли, пока они не дожидаются заданное количество времени, закройте трубу.
2 голосов
/ 27 марта 2012

Почему сервер не может просто создать больше каналов? Падение производительности в сценарии, который вы описываете, не является проблемой, если это происходит редко.

т.е. если труб обычно достаточно для обхода, что имеет значение, если вы используете CreateFile/Sleep вместо WaitForMultipleObjects? Хит производительности не имеет значения.

Я также должен подвергнуть сомнению необходимость перекрывающегося ввода-вывода в клиенте. С сколькими серверами он одновременно общается? Если ответ меньше, скажем, 10, вы можете разумно создать поток для каждого соединения.

По сути, я говорю, что, по-моему, причина отсутствия перекрытия WaitforNamedPipe заключается в том, что нет разумного варианта использования, который требует этого.

...