Создать поток так же, как если бы это было отдельное приложение в C # - PullRequest
2 голосов
/ 04 сентября 2010

У меня было несколько исключений при попытке использовать WebBrowser в многопоточном приложении.COM-компонент, защищенная память и другие исключения везде, где я работаю с WebBrowser.Я просто сдался и вернулся к моей однопоточной версии, которая прекрасно работает.Я бы опубликовал код, но трудно найти причину проблемы, когда я получаю исключения во многих местах.Таким образом, если как однопоточное приложение работает нормально, и когда я запускаю несколько экземпляров одного и того же приложения, оно также работает нормально, должен быть способ имитировать несколько приложений, запущенных из одного приложения, без необходимости фактически создавать отдельное приложениечто я бы запустил из основного приложения.Мой вопрос, поэтому, как я могу заставить Windows обрабатывать мои потоки, как если бы они были разными экземплярами?Это должно устранить проблему, поскольку, как я уже сказал, когда это разные экземпляры, я не получаю никаких исключений.Надеюсь, я достаточно ясен.

Ответы [ 3 ]

2 голосов
/ 04 сентября 2010

WebBrowser является компонентом COM под капотом Internet Explorer. Как и многие COM-компоненты, требуется «однопоточная квартира». Вы должны создать один, чтобы сделать его гостеприимным домом для компонента. В основном два основных требования: поток должен быть инициализирован как STA, и ему нужно прокачать цикл сообщений.

Вот тот, который использует сантехнику, предоставленную Windows Forms:

    private void runBrowserThread(Uri url) {
        var th = new Thread(() => {
            var br = new WebBrowser();
            br.DocumentCompleted += browser_DocumentCompleted;
            br.Navigate(url);
            Application.Run();
        });
        th.SetApartmentState(ApartmentState.STA);
        th.Start();
    }

    void browser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) {
        var br = sender as WebBrowser;
        if (br.Url == e.Url) {
            Console.WriteLine("Natigated to {0}", e.Url);
            Application.ExitThread();
        }
    }

Помните, что событие DocumentCompleted возникает в этом рабочем потоке. Я произвольно использовал это событие, чтобы также завершить поток.

1 голос
/ 04 сентября 2010

Я думаю, что ваша проблема может быть связана с тем, как Microsoft.NET обрабатывает элементы управления пользовательского интерфейса. По сути, любой метод для элемента управления должен вызываться из потока, который его создал (возможно, даже из основного потока пользовательского интерфейса). В противном случае вы получите кучу исключений, связанных с доступом. Я полагаю, что вам нужно будет использовать свойство InvokeRequired и метод Invoke для вызова элемента управления, что также означает, что вам придется определить функцию delgate, которая оборачивает каждый метод, который вы хотите вызвать. Используя в качестве примера свойство WebBroweser.Url, вы можете написать что-то вроде этого:

public delegate void SetWebAddressDelegate ( WebBrowser browser, Uri newUrl);

public void SetWebAddress ( WebBrowser browser, Uri newUrl )
{
    if (browser.InvokeRequired)
        browser.Invoke(new SetWebAddressDelegate(SetWebAddress), browser, newUrl);
    else
        browser.Url = newUrl;
}
0 голосов
/ 04 сентября 2010

Похоже, что вы можете совместно использовать один экземпляр WebBrowser между потоками. Если у каждого потока есть свой экземпляр, и потоки не взаимодействуют друг с другом, я ожидаю, что это будет эквивалентно запуску нескольких экземпляров процесса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...