2012-02-14 3 views
2

Дополнение к Release COM Object in C#Высвобождение COM объектов в фоновом потоке

я заметил, что сохранение MailItem и освобождение является трудоемкой задачей. Итак, безопасно ли сделать следующее? (псевдокод ниже)

Thread 1 (main thread) 
- Open 10 (different .msg files) - MailItems [List<MailItem> items] 
- user works on them and want to save and close all of them with one click. 

- On_save_All_click (runs on main thread) 
- Do 
- toBeClearedList.addAll(items); 
- items.clear() [so that main thread cannot access those items] 
- BG_Thread.ExecuteAsyn(toBeClearedList); 
- End 

Thread 2 (background thread) (input - List<MailItems>) 
- foreach(MailItem item in input) 
    item.save(); 
    System.Runtime.InteropServices.Marshal.ReleaseComObject(item) 
- done 

Я написал пару тестов и выглядит как его работа; Просто хочу знать, безопасно ли это сделать? «Высвобождение COM объектов в другом потоке, чем тот, в котором он был создан»

Благодарности

Karephul

ответ

2

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

Вы :, чтобы увидеть небольшую разницу между вашим кодом и высвободить объекты из основного потока в одном цикле. Если вы отпустите объекты в одном цикле, ваш пользовательский интерфейс будет не отвечать, пока вы не отпустите все сообщения. Используя дополнительный поток, ваш поток пользовательского интерфейса выдает одно сообщение, затем обрабатывает другие события, затем выпускает другой и т. Д. Вы можете получить тот же эффект, отправив себе сообщение (или используя Диспетчер, если у вас есть приложение WPF), и избегайте использования другого потока.

+0

Как вы сказали, единственное, чего я хочу достичь, это «ответный интерфейс». До тех пор, пока безопасно запускать другой поток и освобождать эти COM-объекты безопасно (без каких-либо нежелательных исключений), я хорош. (Я буду продолжать тестирование) – karephul

5

При использовании COM из неуправляемого кода (C/C++) правила довольно строгие: вы можете вызывать методы только на интерфейсе из той же квартиры, на которой вы приобрели объект. Поэтому, если вы получаете указатель интерфейса в потоке STA, то только этот поток разрешен для вызова любого из методов. Если вы получите указатель интерфейса в потоке MTA, тогда только другие потоки в одном MTA могут использовать этот указатель. Любое другое использование, которое пересекает квартиры, требует, чтобы указатель интерфейса был привязан к другой квартире.

Однако, это без изменений мир. .Net добавляет целый слой поверх COM, который зарывает многие из этих низкоуровневых деталей и, по большей части, как только вы получаете доступ к интерфейсу, вы можете передать этот интерфейс вокруг потоков столько, сколько пожелаете, без чтобы беспокоиться о старых правилах пронизывания. Что здесь происходит, так это то, что он фактически передает ссылки на объект, называемый «Runtime Callable Wrapper» (RCW), и управляет базовым COM-интерфейсом и контролирует его доступ к нему. (Он берет на себя ответственность за соблюдение правил COM-квартиры, так что вам этого не нужно, и поэтому может показаться, что старые правила потоковой передачи COM не применяются в .Net: они делают, они просто скрыты от вы.)

Таким образом, вы можете безопасно вызвать Release или другие методы из другого потока: но имейте в виду, что если исходный поток был STA, то вызов этих методов заставит базовый RCW перевести вызов обратно в исходный поток прав собственности так что он по-прежнему поддерживает подчиненные правила COM. Таким образом, использование отдельного потока, возможно, не даст вам никакой производительности в конце!

Некоторые статьи стоит читать, заполняющие в некоторых деталях здесь:

Смежные вопросы