У меня есть Приложение (Form1) Windows Form, которые позволяют пользователю открывать другого Формы (FormGraph). Для открытия FormGraph App, я использую поток, которые открывают его.
Вот код, который выполняет поток:
private void ThreadCreateCurvedGraph()
{
FormGraph myGraph = new FormGraph();
myGraph.CreateCurvedGraph(...);
myGraph.Show();
}
Моя проблема - это myGraph
закрытое право после того, как это открыто.
1) Делает любой знает, почему это происходит и как сделать myGraph
остаться открытыми?
2) После закрытого пользователя myGraph
, Как я завершаю поток?
Большое спасибо!
Если подготовка данных для формы занимает некоторое время, вы можете сделать это в отдельном потоке, чтобы приложение оставалось отзывчивым. Когда данные будут готовы, вы можете вернуть объект в основной поток и позволить ему показать его.
Вы должны объявить переменную для объекта в форме, а не локально в методе, чтобы она сохранялась при выходе из потока.
Когда вы будете готовы показать форму, вы можете использовать метод Invoke для вызова метода, который будет выполнен в основном потоке.
Форма закрывается, потому что поток завершен и поэтому свободен Буду вместе со своими ресурсами (формой). Чтобы поток продолжал работать, вам понадобится цикл
, например.
private void ThreadCreateCurvedGraph()
{
FormGraph myGraph = new FormGraph();
myGraph.CreateCurvedGraph(...);
myGraph.Show();
while (myGraph.IsOpen)
{
//process incoming messages <- this could be fun on a thread....
}
}
Вам понадобится метод установки IsOpen (например, тайм-аут или кнопка), и, очевидно, вам нужно будет фактически создать IsOpen как свойство формы и установить для него значение true при создании формы.
Я добавлю сюда то же, что и другие пользователи ... У вас должна быть веская причина не использовать основной поток.
Как правило, вам следует избегать манипулирования пользовательским интерфейсом из потоков (создание формы это своего рода манипуляция с пользовательским интерфейсом). Вы всегда должны управлять пользовательским интерфейсом из основного потока.
не создают и не показывают формы в неосновном потоке. сделать это в потоке основной формы.
Или сделайте так:
private void ThreadCreateCurvedGraph()
{
FormGraph myGraph = new FormGraph();
myGraph.CreateCurvedGraph(...);
Application.Run(myGraph);
}
но первая версия лучше
Как насчет того, чтобы показать форму, как если бы это был диалог? Вы можете использовать
private void ThreadCreateCurvedGraph()
{
FormGraph myGraph = new FormGraph();
myGraph.CreateCurvedGraph(...);
myGraph.ShowDialog();
}
. Таким образом вызов будет заблокирован до закрытия формы myGraph. Поскольку у вас есть myGraph, созданный в отдельном потоке, вызывающий блокировку ShowDialog должен блокировать только этот поток.
Проблема не в опубликованном фрагменте. Вам нужно будет запустить новый цикл сообщений с помощью Application.Run () или Form.ShowDialog (). Вам также необходимо позаботиться о свойствах потока, чтобы он мог действовать как поток пользовательского интерфейса. Например:
Thread t = new Thread(() => {
Application.Run(new Form2());
// OR:
//new Form2().ShowDialog();
});
t.SetApartmentState(ApartmentState.STA);
t.IsBackground = true;
t.Start();
Здесь есть несколько неудобных вариантов. Форма не может принадлежать какой-либо форме в вашем основном потоке, что обычно вызывает проблемы с Z-порядком. Вам также нужно будет сделать что-то значимое, когда основная форма потока пользовательского интерфейса закрыта. Здесь небрежно решено с помощью IsBackground.
Windows была разработана для поддержки нескольких окон, работающих в одном потоке. Используйте такой код только в том случае, если вам действительно необходимо. Вам никогда не придется ...
Почему вы создаете форму в новом потоке? Бывают случаи, когда вам нужно использовать новый поток, но в других случаях вы можете использовать form.ShowDialog() в основном потоке.
Основная проблема, которую вы испытываете, заключается в том, что вы не устанавливаете насос сообщений в новой цепочке.
Отметьте
Запуск нескольких потоков пользовательского интерфейса
, чтобы получить хорошее представление о том, как запустить пользовательский интерфейс с высокой пропускной способностью, используя несколько потоков (по одному на форму / группу форм).
Чего вы в основном упускаете, так это вызова Application.Run для настройки перекачки сообщений в отдельном потоке пользовательского интерфейса.
Я думаю, что как только закроется последняя форма насоса сообщений, он утилизируется и закончится.
Обратите внимание, что все это ПРЕДПОЛАГАЕТ, что вы ХОТИТЕ открыть окно в отдельном потоке пользовательского интерфейса ... в противном случае вам нужно будет снова вызвать основной поток пользовательского интерфейса для создания и всех манипуляций с окном, чтобы оно было прикреплено к существующему насос сообщений. Есть ХОРОШИЕ случаи для обоих - один сохраняет мысли простыми, другой позволяет НАМНОГО выше производительность, поскольку каждое окно имеет отдельный насос сообщений и, таким образом, может действовать индивидуально - это, например, часто используется в торговых приложениях, которым может потребоваться обновление графиков на несколько экранов и узкое место при работе в однопоточном пользовательском интерфейсе.
Возможно, это сборка мусора:
После выхода ThreadCreateCurvedGraph()
myGraph
выходит за рамки и закрывается.
Вам нужно организовать способ потока, чтобы удерживать экземпляр и ждать (используя блокирующее ожидание), пока он закроется.
Edit: Например, добавить:
Application.Run(myGraph)
в конец метода.
(См. комментарии от TomTom)