Межпотоковое исключение при настройке владельца WinForms.Form - как это сделать правильно? - PullRequest
7 голосов
/ 11 марта 2011

У меня есть основной поток пользовательского интерфейса, который запускает приложение и создает форму главного окна (назовем его W). У меня также есть дополнительный поток, который я раскручиваю и который создает диалоговое окно (назовем его B).

Я хочу установить владельца диалогового окна B в качестве главного окна W. Настройка владельца B происходит в потоке, который создал B. В основном:

b.Owner = w;

но это выдает исключение между потоками, сообщающее мне, что я пытаюсь получить доступ к объекту W из другого потока.

Поэтому я попытался выполнить код в основном потоке пользовательского интерфейса, используя Control.Invoke в W. Но затем я получаю ту же ошибку, сообщающую, что пытаюсь получить доступ к B из неправильного потока:

System.InvalidOperationException was unhandled by user code
  Message=Cross-thread operation not valid: Control 'B' accessed from a
  thread other than the thread it was created on.
  Source=System.Windows.Forms

Как я должен сделать это правильно?

Ответы [ 3 ]

5 голосов
/ 11 марта 2011

Это небольшая ошибка в Winforms, Windows фактически поддерживает создание владельцем окна, созданного в другом потоке. Есть способ отключить эту проверку, что вы должны никогда делать. За исключением случаев, когда вы должны предположить:

    private void button1_Click(object sender, EventArgs e) {
        var t = new Thread(() => {
            Control.CheckForIllegalCrossThreadCalls = false;
            var frm = new Form2();
            frm.Show(this);
            Control.CheckForIllegalCrossThreadCalls = true;
            Application.Run(frm);
        });
        t.SetApartmentState(ApartmentState.STA);
        t.Start();
    }

Я действительно не знаю, если это 100% безопасно, может быть взаимодействие Winforms, которое испортит вещи. Вы находитесь в непроверенных водах, кишащих пронзительными акулами.

3 голосов
/ 11 марта 2011

B необходимо создать в потоке пользовательского интерфейса.

Вы все еще можете взаимодействовать с B из вторичного потока, используя Control.Invoke.

2 голосов
/ 11 марта 2011

Если вы на самом деле запускаете два цикла сообщений в разных потоках, то нет способа сделать то, что вам нужно. Если вы хотите, чтобы W принадлежал B, вам нужно будет создать B в главном потоке и Invoke все ваше взаимодействие с B из второго потока.

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