| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > WPF и Silverlight > Пауза в расчетах без паузы в отрисовке Gui |
| Автор: dAlex 17.5.2011, 14:02 | ||||
| Иногда в расчетах необходимо делать паузу (для того, чтобы успели примениться изменения) в одну-две секунды. Если делать
окно при этом также подвисает. Как сделать отрисовку окна отдельно? Функции, в которых делается пауза, вызываются так
|
| Автор: likegift 17.5.2011, 14:45 |
| а вы что считаете в main-thread? |
| Автор: SergeyLoginov 17.5.2011, 15:01 | ||
Не совсем уверен, что правильно понял, но, возможно, поможет вот это:
Добавлено через 4 минуты и 10 секунд А вообще для длительных вычислений вроде как используется BackgroundWorker там... А UI обновляется в Dispatcher.BeginInvoke(). Что-то мне подсказывает, что задача вовсе не требует пауз в одну-две секунды |
| Автор: dAlex 17.5.2011, 18:50 |
| likegift, SergeyLoginov, да там не совсем расчеты, там биржевая торговля и в определенных местах после отправки заявки на биржу надо чуть чуть подождать, потому что принимается не сразу. То есть тут не нагрузка на процессор, но пауза нужна =) просто у меня UI обновляется сам, после изменения полей |
| Автор: likegift 17.5.2011, 20:42 |
| А нельзя в таком случае делать асинхронную отправку данных с обработкой события по завершению? |
| Автор: -Mikle- 17.5.2011, 21:41 |
| Вообще, любые реализации типа "чуть чуть подождать" разрушительны. Вы не можете гарантировать, что за 1-2 секунды произойдет сетевое(!!!) ожидаемое вами событие. Всегда надо использовать способ, как написал likegift. Реализация его тоже зависит от ваших бизнес-процессов. |
| Автор: dAlex 18.5.2011, 09:12 |
| likegift, -Mikle-, это на будущее =) но даже если так, пока будем ждать события, gui также подвиснет. Тем более, тут такая кривая система, что у нее не узнать, сделано ли действие, потому что оно, по идее, должно делаться мгновенно. |
| Автор: -Mikle- 18.5.2011, 13:01 |
А это зависит от приложения уже. Как сделаешь, так и будет. События не обязаны исходить из основного потока. На данный момент, могу посоветовать только выполнять действия "операция1-подождать-операция2" в отдельном потоке (BackgroundWorker например) и синхронизировать их с основным (если нужно). |
| Автор: dAlex 19.5.2011, 11:42 | ||||
| пытаюсь делать backgroundworker, но что-то запуталась по msdn
но в том месте, где мне надо запустить backgroundWorker, мне мою функцию надо передать со своим параметром. Как это сделать? |
| Автор: likegift 19.5.2011, 13:03 | ||
|
| Автор: dAlex 19.5.2011, 13:59 |
| а в TimeConsumingOperation обязательно добавлять параметры bw и arg? зачем они нужны? upd: так, с arg ясно, это как раз наш SuperPuperParam |
| Автор: likegift 19.5.2011, 14:11 |
| а у вас аргумент какого типа? |
| Автор: dAlex 19.5.2011, 14:22 | ||||
| likegift, тут свой тип Trade =) сделала так
но такое ощущение, что Core.CheckNewStrike вообще не выполняется |
| Автор: likegift 19.5.2011, 15:31 | ||
| dAlex, TimeConsumingOperation - это просто метод из примера, без него можно жить, но с ним удобнее
а проверить то никак? на консоль там вывести или в лог.. |
| Автор: -Mikle- 19.5.2011, 15:37 |
| или брикпоинт поставить... |
| Автор: dAlex 20.5.2011, 11:08 | ||||
ага, оно ругается на
я попробовала вызывать так
но такая же ошибка, как правильно вызвать? |
| Автор: -Mikle- 20.5.2011, 12:56 |
| То что происходит в методе backgroundWorker_DoWork выполняется в отдельном потоке. Следовательно, вся цепочка методов вызываемая из него тоже выполняется в отдельном потоке. Снхронизировать вторичные потоки с основным ты уже научилась. |
| Автор: dAlex 20.5.2011, 13:05 |
| а нужно Invoke или BeginInvoke? |
| Автор: -Mikle- 20.5.2011, 13:32 |
| Это смотря по задаче. Если нужно, чтобы вторичный поток дождался пока отработает основной, то Invoke, а если нет (просто дать команду основному потоку), то BeginInvoke. |
| Автор: dAlex 20.5.2011, 14:27 | ||
тогда функция выполняется, но при паузе в ней gui также подтормаживает
|
| Автор: -Mikle- 20.5.2011, 14:36 |
| Нее... ты не поняла меня... Какой смысл создавать отдельный поток, если в нем ты все что там делается отдаешь опять основному потоку? Dispatcher.Invoke надо использовать поместно, только вокруг тех участков, которые работают непосредственно с ГУИ. Вообще, в идеале, таких участков в асинхронном выполнении должно быть минимум или даже ноль. |
| Автор: dAlex 20.5.2011, 14:37 |
| -Mikle-, а там же везде идет работа со свойствами, и таких участков очень много =( вся функция только и делает, что с ними работает |
| Автор: -Mikle- 20.5.2011, 14:42 |
| Ну тогда нет смысла ее в отдельный поток ставить. Добавлено через 42 секунды А с какими свойствами? С GUI'шными? |
| Автор: dAlex 20.5.2011, 14:44 |
| -Mikle-, да, с теми, что внутри Core, там кучка данных и они все отображаются на форме |
| Автор: -Mikle- 20.5.2011, 17:37 |
| То есть единственная связь вторичного потока с основным потоком происходит только через событие PropertyChanged? В этом методе нет или очень мало прмых обращений к контролам (типа button1.Content, listBox1.Items.Add) ? Все происходит через биндинг? Если да, то есть одно предложение... |
| Автор: dAlex 23.5.2011, 09:19 |
| -Mikle-, да, только через биндинг |
| Автор: -Mikle- 23.5.2011, 17:17 | ||
Тогда есть предложение: положить вызов события PropertyChanged в диспетчер.
Теперь, вызов установки свойств будет происходить в вызывающем потоке, а нотификация об их изменении в основном потоке приложения. Ради эксперимента попробуй вместо асинхронного BeginInvoke использовать синхронный Invoke. Если ГУИ начнет страшно тормозить, то верни BeginInvoke. PS: Надеюсь, что между установками свойств в коде есть значимые временные промежутки (хотя бы порядка 10 мс), иначе ГУИ будет все равно тормозить. |
| Автор: dAlex 24.5.2011, 11:27 |
| сделала, все равно тормозит. Тут же дело просто не в самих расчетах и обновлении gui (так это происходит достаточно быстро), а в присутствии этой паузы. Как раз пока она происходит, gui и подвисает. Надо ее как-то вызвать по-другому, но как? |
| Автор: -Mikle- 24.5.2011, 15:55 |
| Так, минуту... Ты вызываешь свой хитрый метод из бэкграундворкер? Ты убрала код с диспетчером из бэкграундворкер? То есть щас в lalala_DoWork стоит просто вызов без Dispatcher.Invoke? |
| Автор: dAlex 25.5.2011, 10:13 |
| нет, не из воркера, а как раньше, сразу Dispatcher.Invoke. Попробую с воркером =) |
| Автор: dAlex 25.5.2011, 10:39 | ||||||||
| а нужно все-таки просто вызов без Dispatcher.Invoke или с ним? сейчас так
в итоге снова ругань на
|
| Автор: -Mikle- 25.5.2011, 12:05 |
Да, именно так я и предлогал. Значит есть еще где-то места, в которых из метода CheckNewStrike идет обращение к GUI, потому что PropertyChanged, на которых сидит биндинг, стабильно вызывается в потоке GUI. Посмотри внимательно еще раз. |
| Автор: dAlex 25.5.2011, 13:12 | ||||
| а это может быть связано с тем, что backgroundWorker вызывается из таймера? первая ругань происходит в строчке, где меняется Cc_collection, а это точно свойство upd: в строке типа такой
всё в порядке, а если делать
как раз и вылезает ексепшн. Может, там нужен не PropertyChanged, а именно CollectionChanged? раз Add |
| Автор: -Mikle- 25.5.2011, 13:46 |
| Если строчка Cc_collection.Add(..) имеется где-нить в иерархии вызовов методов начиная с метода CheckNewStrike, то да, проблема в этом. Если таких строчек не много, то передайте только эту одну строчку в синхронное выполнение GUI - Dispatcher.Invoke(......Cc_collection.Add(..) .....) |