Даже не знаю как описать проблему. Расскажу лучше что делаю:
Есть оконное приложение (С#), в котором создаётся вторичный поток. В этом потоке происходит вызов MessageBox.Show(...).
Задача:
Необходимо чтобы родителем этого диалогого окна (MessageBox-а) был объект главного класса Form, который естственно находится в другом потоке
Заранее благодарен
25.09.07 08:08: Перенесено модератором из '.NET' — TK
Читайте про Control.Invoke/Control.BeginInvoke (а также о BackgroundWorker для общего развития). Но вообще сама необходимость показывать модальный диалог из worker thread скорее всего говорит о неверном проектировании.
Re[2]: Проблемы с многопоточностью
От:
Аноним
Дата:
21.09.07 13:34
Оценка:
Здравствуйте, Mab, Вы писали:
Mab>Здравствуйте, Tyoma Developer, Вы писали:
Mab>Читайте про Control.Invoke/Control.BeginInvoke (а также о BackgroundWorker для общего развития). Но вообще сама необходимость показывать модальный диалог из worker thread скорее всего говорит о неверном проектировании.
Я не автор топика, но возникает вопрос — а как отображать исключения, возникшие в параллельных потоках ?
Здравствуйте, _FRED_, Вы писали:
А>>…а как отображать исключения, возникшие в параллельных потоках ?
_FR>
Mab>Читайте про Control.Invoke/Control.BeginInvoke (а также о BackgroundWorker для общего развития).
зачем усложнять, если потоку так нужны свои диалоги — без проблем, для этого нужно запустить в этом потоке свой message pumping цикл и не нужно никаких инвоуков...
Другое дело если потоку нужно изменить форму или контрол, которые были создана в чужом потоке... Тогда конечно invoke...
Здравствуйте, _Morpheus_, Вы писали:
_M_>зачем усложнять, если потоку так нужны свои диалоги — без проблем, для этого нужно запустить в этом потоке свой message pumping цикл и не нужно никаких инвоуков...
Я не считаю это достойным workaround-ом
... << RSDN@Home 1.2.0 alpha rev. 717>>
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
_M_>>зачем усложнять, если потоку так нужны свои диалоги — без проблем, для этого нужно запустить в этом потоке свой message pumping цикл и не нужно никаких инвоуков...
_FR>Я не считаю это достойным workaround-ом
почему? Может диалог потока должен жить полностью самостоятельной жизнью, а число обращений к нему этого потока может быть очень высоко, и что теперь, нагружать основной поток приложения дополнительной работой внушительного размера, нагружать код Invoke'ами? Учитывая что потоку глубоко наплевать на формы основного потока, он к ним не обращается, а обращается лишь к своему диалогу, который основному потоку тоже по барабану — это будет вполне логичное решение. Т.к. по сути мы запускаем еще один оконный процесс внутри тогоже процесса, мы можем избавиться от межпроцессного взаимодействия и увеличить скорость.
Здравствуйте, УВАЖАЕМЫЙ _Morpheus_, Вы писали:
_M_>Здравствуйте, _FRED_, Вы писали:
А>>>…а как отображать исключения, возникшие в параллельных потоках ?
_FR>>
Mab>Читайте про Control.Invoke/Control.BeginInvoke (а также о BackgroundWorker для общего развития).
_M_>зачем усложнять, если потоку так нужны свои диалоги — без проблем, для этого нужно запустить в этом потоке свой message pumping цикл и не нужно никаких инвоуков...
_M_>Другое дело если потоку нужно изменить форму или контрол, которые были создана в чужом потоке... Тогда конечно invoke...
А не могли бы Вы кинуть ссылку на источник, как запустить "message pumping цикл"? Если уж самому трудно код написать. Зачем это bla-bla-bla? Я новичок, пришел на форум чему-то научиться, а тут все — или нагугл посылают, или в msdn... Какая тогда ценность форума rsdn? Пообщаться с двумя-тремя старыми соратниками, понимающими Вас с полуслова? (да и то, только потому, что несколько лет назад Вы сами также мучались и кто-то Вас научил, не пустоловными разглагольствованиями, а кодом, да еще, может, Ваш код фиксал) Общайтесь в аське, не позорьте форум, не превращайте его в то, во что украинские политики превратили Украину (я как раз там сейчас).
Да, может быть, "западло" (эмоции уже берут верх в моих рассуждениях) отвечать одно и то же из года в год, кидать давно надоевшие всем ссылки, но что делать, если в этом году в программирование приходят новые десятки тысяч человек, а толковых книг Вы и Ваши умудренные "ректальными отношениями" коллеги все не пишете и не пишете? А что Вы будете отвечать новичкам в следующем году? Через 5 лет?
Надоело заниматься копипастом своих старых ответов? Займитесь изучением новых технологий, другим видом жизнедеятельности, в конце-концов. Пусть ответят те, кто ХОЧЕТ ПОМОЧЬ. Никто не ответит? Да, потому что боятся получить в ответ на свой пост оскорбительные фразы, подкрепленные "улыбками" и "плюсами".
Я не только лично Вас критикую. Я посмотрел, многие участники занимают позиции часто деструктивные по отношению к автору топика. Автор уже и не участвует в обсуждении, он не интересен никому, все забыли про него.
Это критика, хорошая, или плохая — какая есть. Форум msdn собрал самых знающих, самых толковых, самых компетентных. И чем они занимаются? Какую миссию выполняют? На что тратят свое время?
"Может диалог потока должен жить полностью самостоятельной жизнью, а число обращений к нему этого потока может быть очень высоко, и что теперь, нагружать основной поток приложения дополнительной работой внушительного размера, нагружать код Invoke'ами? Учитывая что потоку глубоко наплевать на формы основного потока, он к ним не обращается, а обращается лишь к своему диалогу, который основному потоку тоже по барабану — это будет вполне логичное решение."
Что это? Зачем это?
Не думал, что мой вопрос вызовет такое бурное обсуждение. Но всё же, не понимаю почему некоторые считают, что использование диалоговых окон в потоках, это признак неверного проектирования. Могу просто кратко обрисовать задачу:
Есть некоторое приложение у которого есть функция автоматического update-а (скачивание новой версии). Когда приложение запускается, оно проверяет наличие новой версии в нэте и если таковое обнаруживается, то появляется MessageBox с вопросом: "Не хотите ли обновить". Так вот эту проверку с диалогом я хочу запустить в отдельном потоке, т.к. не всегда эта проверка проходит быстро, а я не хочу чтобы она тормозила работу приложения
Буду рад если кто-нить подскажет иной путь решения этой проблемы. Насчёт Invoke, я его и юзаю, но вы просто наверно не представляете проблемы
public static void CheckForUpdate(bool ShowMessage) {
...
// Вот тут мне нужно получить ссылку на главную форму, но т.к. этот метод запушен в другом потоке....
// Может я зря это делаю, но пока не нашёл другого решенияif (MessageBox.Show(!!!Pointer HERE!!!, "New version of " + System.Windows.Forms.Application.ProductName + " is available" +
"\r\n Do you want to download and update it?",
"New version is available",
MessageBoxButtons.YesNo,
MessageBoxIcon.Question) == DialogResult.Yes) {
...
}
}
// вот что-то типа такого я делаю ---------------------------------------private void FormMain_Load(object sender, EventArgs e) {
m_CheckForUpdateThread = new Thread(new ThreadStart(CheckForUpdate));
m_CheckForUpdateThread.Start();
}
public void GetFormMainPtr(ref FormMain FormMainPtr) {
if (this.InvokeRequired) {
GetFormMainPtrCallback callback = new GetFormMainPtrCallback(GetFormMainPtr);
this.Invoke(callback, new object[] {FormMainPtr});
}
else {
FormMainPtr = this;
}
}
//Но это естественно не работает -----------------------------------------
Автору предыдущего ответа
Я конешно понимаю вас но хочу сказать, что иногда лучше самому в чём-то покапаться, чём требовать сразу готовенькое. Так ничему не научишся.
Здравствуйте, gandjustas, Вы писали:
G>Здравствуйте, Tyoma Developer, Вы писали:
G>Попробуй внести код мессадж бокса в метод, для которого вызывается Invoke
Проблема в том, что мне на данном этапе необходимо получить ссылку на объект главной формы, который был создан в другом потоке и не важно где будет располагаться код.
Здравствуйте, Tyoma Developer, Вы писали:
TD>Есть некоторое приложение у которого есть функция автоматического update-а (скачивание новой версии). Когда приложение запускается, оно проверяет наличие новой версии в нэте и если таковое обнаруживается, то появляется MessageBox с вопросом: "Не хотите ли обновить". Так вот эту проверку с диалогом я хочу запустить в отдельном потоке, т.к. не всегда эта проверка проходит быстро, а я не хочу чтобы она тормозила работу приложения
Расуждаешь ты верно, но выводы делаешь ошибочные. Проверка долгая? Сделай её в отдельном потоке. Потом, если обновления появились, сообщи в главный поток об их наличии и заверши поток. Главный поток должен будет спросить пользователя, не нужны ли ему обновления. Если нужны, то запускается ещё один служебный поток для загрузки обновлений и опять, когда все обновления загружены, надо спросить главный поток: готовы ставить? И начать установку.
... << RSDN@Home 1.2.0 alpha rev. 717>>
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, Tyoma Developer, Вы писали: TD>Буду рад если кто-нить подскажет иной путь решения этой проблемы. Насчёт Invoke, я его и юзаю, но вы просто наверно не представляете проблемы
Наверное ты просто не понимаешь, что такое Invoke.
public static void CheckForUpdate(bool ShowMessage) {
...
// Вот тут тебе не нужно получить ссылку на главную форму, т.к. этот метод запушен в другом потоке. Надо запустить мессаджбокс в нужном потоке:if(AskUserForDownload())
{
...
}
}
// вот что-то типа такого я делаю ---------------------------------------private void FormMain_Load(object sender, EventArgs e) {
m_CheckForUpdateThread = new Thread(new ThreadStart(CheckForUpdate));
m_CheckForUpdateThread.Start();
}
private bool AskUserForDownload()
{
if (InvokeRequired)
{
return (bool) Invoke(AskUserForDownload);
}
else
return MessageBox.Show(this, string.Format(
@"New version of {0} is available
Do you want to download and update it?")
,"New version is available",
MessageBoxButtons.YesNo,
MessageBoxIcon.Question) == DialogResult.Yes;
}
//это естественно cработает -----------------------------------------
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, Tyoma Developer, Вы писали: TD>>Буду рад если кто-нить подскажет иной путь решения этой проблемы. Насчёт Invoke, я его и юзаю, но вы просто наверно не представляете проблемы S>Наверное ты просто не понимаешь, что такое Invoke. S>
S>public static void CheckForUpdate(bool ShowMessage) {
S> ...
S> // Вот тут тебе не нужно получить ссылку на главную форму, т.к. этот метод запушен в другом потоке. Надо запустить мессаджбокс в нужном потоке:
S> if(AskUserForDownload())
S> {
S> ...
S> }
S>}
S>// вот что-то типа такого я делаю ---------------------------------------
S>private void FormMain_Load(object sender, EventArgs e) {
S> m_CheckForUpdateThread = new Thread(new ThreadStart(CheckForUpdate));
S> m_CheckForUpdateThread.Start();
S>}
S>private bool AskUserForDownload()
S>{
S> if (InvokeRequired)
S> {
S> return (bool) Invoke(AskUserForDownload);
S> }
S> else
S> return MessageBox.Show(this, string.Format(
S>@"New version of {0} is available
S>Do you want to download and update it?")
S>,"New version is available",
S> MessageBoxButtons.YesNo,
S> MessageBoxIcon.Question) == DialogResult.Yes;
S>}
S>//это естественно cработает -----------------------------------------
S>
Спасибо Агромное. Да, действительно я не понимаю что такое Invoke, я ещё не совсем разбираюсь в принципах построения многопоточных приложений.
Здравствуйте, Tyoma Developer, Вы писали:
G>>Попробуй внести код мессадж бокса в метод, для которого вызывается Invoke
TD>Проблема в том, что мне на данном этапе необходимо получить ссылку на объект главной формы, который был создан в другом потоке и не важно где будет располагаться код.
и кто вас учит статики кругом пихать?
private void formMainCheckUpdateProc(bool ShowMessage)
{
//...if(this.InvokeRequired)
Invoke(updateRequest, null);
else
updateRequest();
//...
}
private void updateRequired()
{
// Вот тут мне нужно получить ссылку на главную форму, но т.к. этот метод запушен в другом потоке....
// Может я зря это делаю, но пока не нашёл другого решения// без проблем - получай, this - это ссылка на главную форму...
// более того, этот код будет выполняться из основного потока приложения (того в котором форма создана)if (MessageBox.Show(this, "New version of " + System.Windows.Forms.Application.ProductName + " is available" +
"\r\n Do you want to download and update it?",
"New version is available",
MessageBoxButtons.YesNo,
MessageBoxIcon.Question) == DialogResult.Yes) {
//...
}
}
// вот что-то типа такого я делаю ---------------------------------------private void FormMain_Load(object sender, EventArgs e)
{
m_CheckForUpdateThread = new Thread(new ThreadStart(formMainCheckUpdateProc));
m_CheckForUpdateThread.IsBackground = true;
m_CheckForUpdateThread.Start();
}