2017-02-03 14 views
0

Я пытаюсь найти способ изменить родительский поток потока winform обратно в поток GUI. Прямо сейчас мне нужно создать форму из другого потока, но доступ к ней становится невозможным из основной формы, на которой есть ссылка на нее.Изменить родительский поток формы

здесь пример того, что у меня есть

public partial class MainForm : Form 
{ 
    // local instance of the sub form 
    private ViewForm SubForm { get; set;} = null; 

    public MainForm() 
    { 
     InitializeComponent(); 

     Task.Run(() => 
     { 
      // set the sub form    
      SubForm = new ViewForm(); 
     } 

     // call the rest of the initialization of main form 
     InitializeCustomControls(); 
    } 

    private void OpenViewWindow_Click(object sender, EventArgs e) 
    { 
     // if the window is instanciated 
     if (SubForm != null) 
     { 
      SubForm.Show();     
     } 
    }   
} 

ViewForm окно не является объектом Form. это обычное стороннее окно. Он имеет множество элементов управления и шаблонов, смешанных с темами. Единственный вызов нового пустого конструктора может занять до 7 секунд, поэтому мне нужно создать его в другом потоке, пока я продолжаю загружать основное окно.

Прямо сейчас я могу вызвать любой метод в окне, кроме .Show(), который всегда терпит неудачу из-за ограничения на создание потока. Я хотел бы держаться подальше от создания потока в виде бесконечного потока, который будет ждать и читать какой-то объект, чтобы он рассказывал ему, когда показывать и скрывать окно.

является .Show() ошибка:

Cross-thread operation not valid: Control 'ViewForm' accessed from a thread other than the thread it was created on.

Я попытался следующие, но вместо этого он все еще заморозить мой интерфейс:

Task.Run(() => 
{ 
    // set the sub form 
    this.Invoke(new MethodInvoker(delegate 
    { 
     SubForm = new ViewForm(); 
    })); 
} 

Что я хотел бы что-то, как огонь и забыть создание объекта GUI.

+0

Я не читал весь ваш пост, но название вашего вопроса и первое предложение выделялось. Ответ: вы должны * никогда не запускать код пользовательского интерфейса ни на что иное, кроме основного потока. Это золотое правило в программировании пользовательского интерфейса. Итак, если вы последуете этому, тогда у вас не будет этой проблемы. –

+2

Если у вас есть сторонняя форма, которая замораживает поток пользовательского интерфейса в течение 7 секунд при запуске, тогда у него есть основная ошибка. Либо не используйте эту багги-стороннюю форму, либо исправьте ошибку. – Servy

+0

@ rory.ap Хотя это была моя первая реакция, код ошибки, по-видимому, находится в стороннем коде, поэтому это не правило, которое OP в состоянии обеспечить. – Servy

ответ

0

Here's раствор с помощью BackGroundWorker:

public partial class MainForm : Form 
{ 
    // local instance of the sub form 
    private ViewForm SubForm { get; set;} = null; 

    public MainForm() 
    { 
     InitializeComponent(); 
     backGroundWorker1.RunWorkerAsync(); 
     InitializeCustomControls(); 
    } 

    private void OpenViewWindow_Click(object sender, EventArgs e) 
    { 
     // if the window is instanciated 
     if (SubForm != null) 
     { 
      SubForm.Show();     
     } 
    } 

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
    { 
     SubForm = new ViewForm(); 
    } 
} 

Испытано создания двух форм, MainForm довольно много, как в вашей выборке и SubView формы с Threading.Sleep(10000) на конструкторе.

+0

это прекрасно работает, и мне не нужно m отображается как трюк @Gusman. Это будет очень полезно, поскольку у меня есть пара этих окон для предварительной загрузки, когда они будут готовы. – Franck