2010-03-18 3 views
5

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

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

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

ответ

0

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

Или это:

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

но первый вариант лучше

+0

Это то, что он делает. – TomTom

+0

внимательно прочитайте: «Я использую поток, который его открывает». – Andrey

+0

Прочтите его код. Проблема: не установлен насос сообщений. вот веские причины для того, чтобы иметь несколько потоков пользовательского интерфейса ». Когда-либо видели однопоточное торговое приложение - они SUCK (намек: NinjaTrader - отстой для этого). – TomTom

0

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

+0

создание формы не точно .... манипуляция. – TomTom

+0

Если вы считаете, что Forms является лишь частью пользовательского интерфейса, а не контейнером для пользовательского интерфейса, то это так. – dbemerlin

+0

все еще не так. Существуют большие случаи для нескольких потоков пользовательского интерфейса. – TomTom

0

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

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

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

+0

Не то, что пользователь спрашивает. он совершенно ясно видит в ХОТИТЕ открыть другое окно в отдельном потоке пользовательского интерфейса, которое, кстати, иногда имеет ДЕЙСТВИТЕЛЬНО хорошие причины (торговые приложения хорошо известны для этого). – TomTom

+1

@TomTom: Пожалуйста, не пытайтесь принять решение о том, что действительно хочет OP. Понятно, что в настоящее время используется поток, но неясно, что это действительно желаемое решение. Просто потому, что ОП требует чего-то, не обязательно означает, что это правильное решение. Если бы кто-то только спрашивал о том, что было задано, на множество вопросов нельзя было ответить ничем иным, кроме «да» или «нет», поскольку вопрос, на самом деле заданный, не был тем, что подразумевалось под вопросом. – Guffa

+0

, пожалуйста, не пытайтесь сделать постановление о том, что действительно хочет. Прочтите его сообщение. Следуйте его примеру и вычитайте, что он пытается сделать. Не думайте, что программист - бессвязный идиот. – TomTom

0

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

например.

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 как свойство формы и установить его верно, когда создается форма ,

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

+0

Так много людей здесь не знают, что происходит с несколькими сообщениями - это больно. RTFM, ребята. Существуют ДЕЙСТВИТЕЛЬНО хорошие причины для создания многопоточного пользовательского интерфейса - у меня есть до 6 потоков пользовательского интерфейса для 6 окон. Которые все заняты перекрашиванием. Это полностью поддерживается. – TomTom

1

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

Проверить

Run multiple UI Threads

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

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

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

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

-1

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

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

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

Edit: Например добавить:

Application.Run(myGraph) 

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

+0

Нет, пользователю необходимо установить MESSAGE PUMP для обработки сообщений Windows нового потока пользовательского интерфейса. – TomTom

+0

@TomTom: Это: 'Application.Run (myGraph)', который будет удерживать экземпляр и ждать его закрытия? – quamrana

+0

Точно. Он установит насос сообщений и подождет, пока последнее окно на нем не закроется. Это похоже на то, что происходит в основном потоке, который при запуске также не связан с подключением к пользовательскому интерфейсу (вот почему вы читаете Application.Run). – TomTom

-1

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

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

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

+0

Не решение и полное обход того, что не так. – TomTom

+0

Отличная идея! Думаю, я сделаю, как сказал. – menachem

+0

Насколько я знаю, это работает, поэтому я не знаю, почему вы даете мне отрицательные голоса. –

5

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

+0

Отлично, за исключением последней части - вам никогда не придется. Когда-либо видели торговое приложение, которое ... делает так много обновлений, пользовательский интерфейс отстает на 6 экранах;) Существует необходимость. – TomTom

+0

@TomTom: Я не знаю, почему здесь не так, чтобы поставить ShowDialog здесь, как я сказал. –

0

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

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