Многопоточная перекачка сообщений без использования второй формы

У меня есть приложение C #, которое использует компонент COM. Для обработки этого COM-компонента требуется насос сообщений (Application.Run ()). Это означает, что он застрял в основном потоке. Но недавно я обнаружил, что можно запустить другое Application.Run в другом потоке, который получает свой собственный ApplicationContext.

Поэтому я хочу разместить компонент COM в отдельном потоке внутри своего собственного Application.Run (), но я не могу понять, как начать работу в новом потоке, не создавая формы пользовательского интерфейса.

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

Я пробовал всевозможные запутанные вещи, такие как установка фильтра сообщений (сообщения не возникают в новом потоке), копирование контекста выполнения в другой поток и попытки получить оттуда SynchronizationContext (он отказывается копировать ExecutionContext из уже запущенный поток), получение Thread.CurrentContext перед запуском Application.Run (), а затем вызов DoCallbBack () (DoCallback заканчивается в исходном потоке) и т. д. Ничего из того, что я пробовал, не работает.


person Bryce Wagner    schedule 15.09.2009    source источник


Ответы (1)


Брайс,

Возможно, вам удастся адаптировать этот фрагмент из доклада Андерса Хейлсберга о «Будущем C #». Это небольшой класс, который добавляет к потоку насос сообщений, чтобы он мог открывать окна с помощью цикла REPL, и к ним будет прикреплен насос сообщений.

Код выглядит так:

using System.Windows.Forms;
using System.Threading;
class UserInterfaceThread()
{
    static Form window;

    public UserInterfaceThread() 
    {
        var thread = new Thread(() => {
            window = new Form();
            var handle = window.Handle;
            Application.Run();
            });
        thread.Start();
    }
    public void Run(Action action)
    {
        window.Invoke(action);
    }
}

Обсуждение этого кода происходит через 1 час 5 минут после выступления Андерса, если вы хотите его просмотреть.

person Robert Harvey    schedule 15.09.2009
comment
Таким образом, оказывается, что создание дескриптора окна - это то, что создает экземпляр SynchronizationContext, а не Application.Run (). Поэтому просто вызываем IntPtr handle = new Form (). Handle; создает требуемый контекст WindowsFormsSynchronizationContext перед вызовом Application.Run (). Большое спасибо. - person Bryce Wagner; 15.09.2009