Получить mainThread для запуска снова? - PullRequest
0 голосов
/ 21 сентября 2011

Привет,

У меня есть приложение winform, на котором размещается служба WCF (NamedPipes).При получении вызова будет инициировано событие, а затем будет создана и открыта форма.Проблема в том, что я получаю следующее исключение

ActiveX control '8856f961-340a-11d0-a96b-00c04fd705a2' cannot be instantiated because the current thread is not in a single-threaded apartment.

При создании System.Windows.Forms.WebBrowser в методе winforms InitializeComponent?

Предполагаю, что другой поток выполняет четный (рабочий поток), как я могу получить основной поток для запуска события?

В то время у меня нет открытой winform, поэтому я не могу использовать InvokeRequired.

BestRegards

Edit1: не рад, что я использую

[STAThread]
public static void Main(string[] args)
{
Application.Run(_instance);
}

Ответы [ 3 ]

1 голос
/ 21 сентября 2011

Такие вызовы выполняются в потоках пула потоков. Они не подходят для отображения любого пользовательского интерфейса. Вам нужно создать собственную нить с правильным вкусом:

        var t = new Thread(() => {
            Application.Run(new Form1());
        });
        t.SetApartmentState(ApartmentState.STA);
        t.Start();

Есть и другие практические проблемы, с которыми вы будете сталкиваться, вы не можете просто открыть окно без участия пользователя. Типичные ошибки: пользователь случайно закрывает его, даже не видя его, или окно исчезает за окном, с которым он работает. Если у вас уже есть пользовательский интерфейс, то обязательно используйте Control.BeginInvoke (), чтобы основной поток отобразил окно. Подумайте о мягком прикосновении к NotifyIcon, отображающему всплывающую подсказку в области уведомлений в области уведомлений.

0 голосов
/ 04 октября 2011

Мое решение заключается в создании фиктивной winform при запуске, и когда мне понадобится основной поток пользовательского интерфейса, я буду использовать invoke для этой фиктивной формы.

Он будет использовать больше ресурсов, но я не вижу более простого способа сделать это.

0 голосов
/ 21 сентября 2011

Этот вызов WCF, скорее всего, поступает в поток, отличный от основного потока пользовательского интерфейса. Все элементы управления пользовательского интерфейса, включая элементы ActiveX, должны создаваться и доступны из потока пользовательского интерфейса и только из потока пользовательского интерфейса. Полученная ошибка указывает на то, что поток создания отсутствует даже в однопотоковой квартире (STA), что также является требованием.

Чтобы получить код, выполняющийся в основном потоке пользовательского интерфейса, используйте метод Control.Invoke. Это приведет к выполнению делегата в потоке, в котором находится цель Control или Form.

Если у вас нет ссылки на Control или Form, сразу же доступной, вам нужно будет создать ее. Возможно, вам придется создать поток, который также запускает цикл сообщений. Это можно сделать с помощью Application.Run. Достаточно просто создать скрытый Form, который можно использовать для вызова Invoke.

Вот как это может выглядеть.

void SomeMethodExecutingOnThreadPool()
{
  var form = null;
  var mre = new ManualResetEvent(false);

  // Create the UI thread.
  new Thread(
    () =>
    {
      form = new Form();
      form.Load += 
        (sender, args) => 
        {
          mre.Set();
        }
      Application.Run(form);
    }).Start();

  // Wait for the UI thread to initialize.
  mre.WaitOne(); 

  // You can now call Invoke.
  form.Invoke(/* ... */);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...