Многопоточная прокачка сообщений без второй формы - PullRequest
4 голосов
/ 15 сентября 2009

У меня есть приложение 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 заканчивается в исходном потоке) и т. Д. Ничего из того, что я пробовал, не работает.

1 Ответ

6 голосов
/ 15 сентября 2009

Bryce,

Возможно, вы сможете адаптировать этот фрагмент из Доклад Андерса Хейлсберга о "Будущем 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 минут после выступления Андерса, если вы хотите его просмотреть.

...