2016-07-13 5 views
0

Итак, у меня есть это приложение с MainForm, на котором есть несколько кнопок. и кнопки будут занимать много времени, включая работу с интерфейсом MainForm. Поскольку несколько раз нам нужно запускать несколько экземпляров этого приложения в одно время, я решил создать MainFormHost, где это форма с элементом управления вкладкой, который под каждой вкладкой создавал экземпляр моего MainForm и размещал его там. И пока все в порядке. Проблема в том, что когда я нажимаю кнопку на MAINForm1, она начинает работать нормально, но как только я нажимаю кнопку на MainForm2, процесс MainForm1 запускается в очередь за процессом MainForm2.Хостинг нескольких экземпляров приложения в tabcontrol/queueing

MainForm GetMainFrom(TabPage tabPage) 
{ 
tabPage.Invoke(new Action(() => 
{ 
    mainForm = new MainForm(); 
    mainForm.TopLevel = false; 
    mainForm.FormBorderStyle = FormBorderStyle.None; 
    mainForm.Dock = DockStyle.Fill; 

    _mainForms.Add(mainForm); 
    tabPage.Controls.Add(mainForm); 
    mainForm.Show(); 

})); 
} 

И затем вызвать метод:

var mainFormThread = new Thread(() => 
{ 
    mainForm = GetMainFrom(tabPage); 
}); 

mainFormThread.SetApartmentState(ApartmentState.STA); 
mainFormThread.Start(); 

Я не могу изменить код внутри MainForm для Призовите вещи, когда они хотят работать с UI, потому что это будет слишком много работы, но Я могу легко сделать каждый щелчок кнопки для вызова из потока/задачи или ...

ТИА

ответ

0

Короче говоря, вы можете иметь только один «основной поток», который может взаимодействовать с элементами управления пользовательского интерфейса. Когда-либо. Период. Невозможно обойти это (в стандартном коде вы можете нарисовать свою форму из другого процесса, но я не буду вдаваться в это)

Итак, что вам нужно сделать, это упорядочить код в комплект узор.

  • Методы, которые делают подготовительную работу - это может быть сделано в отдельном потоке (ов)
  • методы, которые позволяют обновить пользовательский интерфейс - должен быть сделан на UI/Main Thread

Идея в том, простая, фоновая работа занимает много времени, а обновление пользовательского интерфейса не должно.

Поскольку у вас есть 1 или 2 длительных действия, работающих под ОСНОВНЫМ ИНТЕРНЕТОМ UI, это «блокирует пользовательский интерфейс» и вызывает поведение, которое вы испытываете.

Блокирует пользовательский интерфейс, то, что вы на самом деле имеете, это насос Windows Message, который не может работать. Таким образом, каждая команда для изменения размера окна или обновления элемента управления в форме - это сообщение в насосе. Это должно работать на основной теме. Если вы выполняете «работу» в этом потоке, например, подключение к базе данных, загрузку файла и т. Д., То насос не может продолжать работу, поэтому вы получите сообщение «это приложение не отвечает».

Таким образом, вы должны загрузить файл или что-либо в потоке, а когда он будет завершен, перейти к потоку пользовательского интерфейса и обновить пользовательский интерфейс, например. например, закончил в текстовом поле.

Способ перехода между двумя потоками (фон на главный) заключается в использовании begininvoke, и вы знаете, если это необходимо, используя «invoke required».

Из MSDN

// This method demonstrates a pattern for making thread-safe 
 
// calls on a Windows Forms control. 
 
// 
 
// If the calling thread is different from the thread that 
 
// created the TextBox control, this method creates a 
 
// SetTextCallback and calls itself asynchronously using the 
 
// Invoke method. 
 
// 
 
// If the calling thread is the same as the thread that created 
 
// the TextBox control, the Text property is set directly. 
 

 
private void SetText(string text) 
 
{ 
 
\t // InvokeRequired required compares the thread ID of the 
 
\t // calling thread to the thread ID of the creating thread. 
 
\t // If these threads are different, it returns true. 
 
\t if (this.textBox1.InvokeRequired) 
 
\t { \t 
 
\t \t SetTextCallback d = new SetTextCallback(SetText); 
 
\t \t this.Invoke(d, new object[] { text }); 
 
\t } 
 
\t else 
 
\t { 
 
\t \t this.textBox1.Text = text; 
 
\t } 
 
}

Это большая статья и поможет вам, где вы должны быть: MSDN about thread safe code and invoke required

+0

Благодарим Вас за тщательное объяснение.Однако я как-то знал большинство из того, что вы объяснили, но мой вопрос состоял в том, что есть способ/ярлык для меня, чтобы не вносить такие изменения в мой код. например, искать что-то вроде создания нескольких потоков пользовательского интерфейса или как это работает, когда я запускаю два экземпляра моего приложения, и они отлично работают, не блокируя друг друга. Я не хочу иметь много открытых окон и предпочитаю, чтобы экземпляры управлялись под управлением табуляции. – Alireza

+0

Помимо нескольких процессов (в основном, несколько копий вашего приложения), то нет, нет. Извините. Самый простой способ «исправить это» - это использовать «Рамку задач». – adudley

Смежные вопросы