Почему моя нить прерывается сразу после показа формы Windows? - PullRequest
5 голосов
/ 18 марта 2010

У меня есть приложение Windows Form (Form1), которое позволяет пользователю открывать другие формы (FormGraph). Чтобы открыть приложение FormGraph, я использую нить, которая его открывает.
Вот код, который запускается потоком:

private void ThreadCreateCurvedGraph()
{
    FormGraph myGraph = new FormGraph();
    myGraph.CreateCurvedGraph(...);
    myGraph.Show();
}

Моя проблема в том, что myGraph закрывается сразу после открытия.
1) Кто-нибудь знает, почему это происходит и как заставить myGraph оставаться открытым?
2) После того, как пользователь закрыл myGraph, как мне прекратить поток?
Большое спасибо!

Ответы [ 9 ]

5 голосов
/ 18 марта 2010

Проблема не в размещенном фрагменте. Вам нужно будет запустить новый цикл обработки сообщений с помощью 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 была разработана для поддержки нескольких окон, работающих в одном потоке. Используйте такой код, только если вам действительно нужно. Тебе никогда не придется ...

1 голос
/ 18 марта 2010

Основная проблема, с которой вы столкнулись, заключается в том, что вы не устанавливаете рассылку сообщений в новой теме.

Проверка

Запуск нескольких потоков пользовательского интерфейса

для хорошего обзора того, как запустить пользовательский интерфейс с высокой производительностью, используя несколько потоков (по одному на форму / группу форм).

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

Я думаю, что как только закроется последняя форма помпы сообщений, она утилизируется и завершится.

Обратите внимание, что все это предполагает, что вы ХОТИТЕ открыть окно в отдельном потоке пользовательского интерфейса ... в противном случае вам необходимо снова обратиться к основному потоку пользовательского интерфейса для создания и всех манипуляций с окном, чтобы оно было присоединено к существующему насос сообщений. В обоих случаях есть ХОРОШИЕ случаи: один сохраняет простоту, а другой позволяет значительно повысить производительность, поскольку каждое окно имеет отдельную рассылку сообщений и, следовательно, может действовать индивидуально - это, например, часто используется в торговых приложениях, которым может потребоваться обновить графики количество экранов и узкое место при использовании однопоточного интерфейса в пользовательском интерфейсе.

0 голосов
/ 18 марта 2010

Почему вы создаете форму в новой теме? Есть моменты, когда вам нужно использовать новый поток, но в других случаях вы можете использовать form.ShowDialog () в основном потоке.

0 голосов
/ 18 марта 2010

Что если вы покажете форму, как будто это диалог? Вы можете использовать

private void ThreadCreateCurvedGraph()
{
     FormGraph myGraph = new FormGraph();
     myGraph.CreateCurvedGraph(...);
     myGraph.ShowDialog();
}

Таким образом, вызов будет блокироваться до тех пор, пока форма myGraph не будет закрыта. Так как myGraph создан в отдельном потоке, вызывающий блокировку ShowDialog должен блокировать только этот поток.

0 голосов
/ 18 марта 2010

Возможно, это сборка мусора:

После выхода ThreadCreateCurvedGraph(), myGraph выходит из области видимости и закрывается.

Вам нужно организовать способ удержания потока в экземпляре и ожидания (с помощью блокировки ожидания) его закрытия.

Редактировать: Например, добавить:

Application.Run(myGraph)

до конца метода.
(См. Комментарии TomTom)

0 голосов
/ 18 марта 2010

Форма закрывается, потому что поток завершен и поэтому свободен вместе со своими ресурсами (форма). Чтобы поток продолжал работать, вам нужна петля

, например

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 при создании формы.

Я добавлю сюда так же, как и другие пользователи ... У вас должна быть веская причина не использовать основной поток.

0 голосов
/ 18 марта 2010

Если для подготовки данных для формы требуется некоторое время, вы можете сделать это в отдельном потоке, чтобы приложение реагировало. Когда данные готовы, вы можете вернуть объект в основной поток и позволить ему показать его.

Вы должны объявить переменную для объекта в форме, а не локально в методе, чтобы она сохранялась при выходе из потока.

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

0 голосов
/ 18 марта 2010

Как правило, вам следует избегать манипулирования пользовательским интерфейсом из потоков (создание формы является своего рода манипуляцией с пользовательским интерфейсом).Вы всегда должны манипулировать пользовательским интерфейсом из основного потока.

0 голосов
/ 18 марта 2010

не создавать и показывать формы в неосновной теме. сделать это в основной форме потока.

Или сделайте это:

private void ThreadCreateCurvedGraph()
{
    FormGraph myGraph = new FormGraph();
    myGraph.CreateCurvedGraph(...);
    Application.Run(myGraph);
}

но первая версия лучше

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