QueueUserWorkItem с COM в C ++ - PullRequest
       41

QueueUserWorkItem с COM в C ++

2 голосов
/ 04 февраля 2010

У меня проблема с производительностью, когда клиенты создают сотни объектов определенного типа "Foo" в DOM моего приложения на C ++. Каждый экземпляр Foo имеет свою собственную асинхронную рабочую очередь со своим собственным потоком. Очевидно, это не масштабируется.

Мне нужно разделить потоки среди рабочих очередей, и я не хочу заново изобретать колесо. Мне нужно поддерживать XP, поэтому я не могу использовать пул потоков Vista / Win7. Работа, которую необходимо выполнить для обработки каждого элемента очереди, включает выполнение COM-вызовов в многопоточной COM-квартире. Документация для пула потоков XP говорит, что можно вызывать CoInitializeEx () с квартирой MTA в обратном вызове рабочей функции потока. Я написал тестовое приложение и убедился, что это работает. Я заставил приложение выполнить 1 миллион итераций с парой CoInitializeEx / CoUninitialize и без нее в функции обратного вызова WorkItem. Это занимает 35 секунд с вызовами CoInit * и 5 секунд без них. Это слишком много для моего приложения. Поскольку пул потоков для каждого процесса и сторонний код выполняется в моем процессе, я предполагаю, что CoInitializeEx () не безопасно использовать один раз для потока и никогда не использовать CoUninitialize ().

Учитывая все это, есть ли способ использовать пул потоков Win32? Я что-то упустил или пул потоков XP довольно бесполезен для высокопроизводительных COM-приложений? Мне просто нужно создать собственную систему совместного использования потоков?

Ответы [ 2 ]

1 голос
/ 04 февраля 2010

Вы убедились, что занимает так много времени? это вызов CoInitializeEx ()? Вам определенно не нужно вызывать CoInitialize один раз для каждой задачи. Вы также не говорите, сколько потоков вы порождаете, т.е. если вы работаете на двухъядерном процессоре и ваша работа интенсивно использует процессор, не ожидайте более чем двухкратного ускорения, и если ваша работа не CPU затем интенсивно ожидает некоторого ресурса (памяти, диска, сети), и ускорения будут аналогичным образом ограничены, возможно, усугубятся, если для этого ресурса будет удерживаться блокировка.

Если вы можете использовать Visual Studio 2010, взгляните на библиотеку Parallel Pattern Library и Asynchronous Agents Library, есть пара инструментов, которые могут помочь сделать это меньше кода для написания.

Если вы не можете, вы можете, по крайней мере, попытаться поместить токен в TLS, который представляет, был ли COM инициализирован в этом потоке, и использовать присутствие этого токена для обхода ваших вызовов CoInitialize, когда они не нужны. *

1 голос
/ 04 февраля 2010

Я предполагаю, что CoInitializeEx () небезопасно один раз для потока и никогда не CoUninitialize ().

Windows очистится, если поток завершится без вызова CoUninitializeзнаю, что это работает, потому что в противном случае не было бы очистки, когда потоки зависают или прерываются.

Таким образом, единственный способ, которым этот взлом мог вызвать проблему, - это когда кто-то пытался поставить в очередь рабочие элементы, которым требовалась квартира STA, что кажется маловероятным.

Я бы соблазнился пойти на это.

...