Что C# эквивалентен из MsgWaitForMultipleObjects?

У меня есть Windows Form с ListView в Режиме Отчета. Для каждого объекта в представлении я должен выполнить длительную операцию, результатом которой является число.

Путем я сделал бы, это в собственном win32 должно создать рабочий поток для каждого объекта (наивно; конечно, я не создам неограниченное количество потоков), и затем MsgWaitForMultipleObjects () на массиве дескрипторов потока. Поскольку каждое вычисление заканчивается, сигнал потоков и основной поток UI просыпаются и обновляют. Тем временем мы качаем сообщения, таким образом, поток UI остается быстро реагирующим.

Кто-либо может обеспечить пример того, как это могло бы работать в C#? Я посмотрел на объект Монитора, и это, кажется, не то, что я хочу — или это качает сообщения при блокировании?

Спасибо.

Править: Это кажется тем WaitHandler. WaitAny () мог бы на самом деле накачать сообщения. См. трактат cbrumme на нагнетании сообщения в CLR.

10
задан i_am_jorf 23 February 2010 в 19:20
поделиться

2 ответа

Я думаю, что долго работающий активный объект - лучший выбор в вашем случае. Основной поток вызывает прокси (активного объекта). Прокси-сервер преобразует метод вызова в сообщение, и это сообщение отправляется в очередь. Прокси возвращает вызывающей стороне будущий объект (это ссылка на будущий результат). Диспетчер выводит сообщения из очереди одно за другим и действительно выполняет вашу задачу в другом потоке (рабочем потоке). Когда рабочий поток завершает задачу, он обновляет результат будущего объекта или вызывает метод обратного вызова (например, для обновления вашего пользовательского интерфейса). Dispather может иметь много рабочих потоков для одновременного выполнения нескольких задач.

Вы можете увидеть эту статью (с образцом) о долго работающем шаблоне активного объекта.

2
ответ дан 4 December 2019 в 04:01
поделиться

Попросите ваш основной поток создать поток менеджера. Для этого вы можете использовать BackgroundWorker . Этот поток диспетчера запускает рабочий поток для каждого элемента в ListView. Это позволит вашему пользовательскому интерфейсу продолжать реагировать на ввод пользователя без зависания во время обработки фоновых потоков.

Теперь проблема в том, как дождаться завершения каждого рабочего потока. К сожалению, мне не удалось найти способ получить дескриптор потока для объектов System.Threading.Thread . Я не говорю, что это невозможно сделать; Я просто не нашел ни одного. Еще один усложняющий аспект заключается в том, что класс System.Threading.Thread запечатан, поэтому мы не можем получить от него какой-то «дескриптор».

Здесь я использую ManualResetEvent .

Допустим, каждый рабочий поток - это просто поток ThreadPool . Управляющий BackgroundWorker создает объект ManualResetEvent для каждого элемента в ListView. Когда BackgroundWorker запускает каждый поток ThreadPool , передайте событие ManualResetEvent в качестве аргумента функции QueueUserWorkItem . Затем непосредственно перед выходом каждого потока ThreadPool установите объект ManualResetEvent .

Поток BackgroundWorker затем может поместить все объекты ManualResetEvent в массив и ожидать этого массива с помощью функций WaitHandle.WaitXXX .По завершении каждого потока вы можете использовать события BackgroundWorker для обновления пользовательского интерфейса или использовать метод Control.Invoke () для обновления пользовательского интерфейса (см. Ответ Марка Гравелла здесь ).

Надеюсь, это поможет.

2
ответ дан 4 December 2019 в 04:01
поделиться
Другие вопросы по тегам:

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