| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Visual C++/MFC/WTL > Как отрисовать объекты из дополнительного потока? |
| Автор: takedo 1.6.2005, 11:51 |
| Люди!!! Вот какая приключилась проблема: Программа должна получать данные из com порта и в соответствии со значениями перерисовывать объекты на CScrollView SDI приложения. Объекты - производные от CButton со стилем BS_OWNERDRAW. Объекты имеют встроенные функции типа SetState(){.... Invslidate();}. В программе много чего ещй есть, но не по суте, поэтому опущено. До тех пор, пока не был создан дополнительный поток, в котором в цикле пробегаем по всем объектам и по Random генерируем данные с вызовом SetState, все работало замечательно. Как только перерисовка стала делаться из потока - появились непонятные Exception. Дело наверное в синхронизации. Так вот вопрос - как это организовать, что надо защищать от совместного доступа и возможно ли это осуществить с применением "рабочего" потока??? Помогите пожалуйста... |
| Автор: Coocky 1.6.2005, 13:15 | ||
| takedo вО ПЕРВЫ . хотелось бы узнать, что Exception выдает. 2.
А вот это зря, интересно было б узнать, ЧТО творится в потоках... |
| Автор: takedo 1.6.2005, 15:08 |
| Собственно программа должна собрать информацию об объектах. Объекты имеют четыре параметра и несколько состояний: активен, неактивен и др. Программа построена на базе SDI. как уже говорилось, объекты произведены от CButton и объеденены на CFrameWnd, являющемся их родителями. В их же родителе вызывается и обработчик события BN_CLICKED для них. При обработке вызывается настройка - произведена от CPropertySheet c двумя вкладками - для просмотра и настройки. В настройке мы должны задавать значения параметров и отсылать их устройству-объекту. Программа должна фоном генерировать запросы через Com порт объектам и получать ответы, изменяя отображение их на экране(то есть перерисовывать в DrawItem кнопки). Если изменилась информация об объекте в момент, когда у него вызвано окно настроек - окно настроек тоже надо перерисовать. Помимо фоновых команд должно быть предусмотрен механизм отсылки команд не в фоне, а по нажатию соответствующей кнопки в окне настроек(при изменении параметров). Но скорее всего надо сперва послать команду на изменение, а затем изменить отображение после получения уже фоновой команды. Так вот, все было хорошо, пока не начал подготавливаться к передаче данных. Создал поток и решил просто пробежаться по всем объектам меняя их состояние(т.е цвет). При завершении программы получается, но не всегда "Unhandled exception at 0x7c34c97a (mfc71ud.dll) in jp.exe: 0xC0000005: Access violation reading location 0x00000020.". Как быть - просто не знаю. Буду очень благодарен, если с чьей - либо помощью удасться решить эту проблему. |
| Автор: Coocky 1.6.2005, 15:10 | ||
takedo
Через отладчик можешь глянуть, в каком месте вылетает? Добавлено @ 15:15 Вообще скажу одно-если обращаешься из разных потоков к одному обьекту, тогда нужна синхронизация |
| Автор: takedo 1.6.2005, 15:18 |
| вылетает в функции UpdateMy окна настроек, при строках типа CEdit* edit = (CEdit*)GetDlgItem(IDC_EDIT_V1); и т.д, в которой и происходит изменение отображения. Также в ней позже вызывается и InvalidateRect но до него и не доходит. Когда это окно закрыто - UpdateMy не вызывается а отображаются только кнопки, нажимая на мышку и сворачивая несколько раз фрейм можно добиться того-же самого. |
| Автор: Coocky 1.6.2005, 15:24 | ||
takedo
Что внизу пишет(watch)- edit=?????? Или что другое, там где остановится, внизу смотри, какя ошибка. |
| Автор: takedo 1.6.2005, 15:27 |
| в том то и дело - не знаю даже какой это объект - может быть CDC??? Хотя только вот вот попробовал посылать ::SendMessage(hwnd,WM_MYMESSAGETOREDRAW,0,0); из потока в кнопку и тоже ничего не дало - все также. я готов и поэкспериментировать в CDialog с одной двумя моими кнопками, лишь бы точно знать как и что делать!!! |
| Автор: Coocky 1.6.2005, 15:28 | ||
takedo
да посмотри при отладке внизу в окне, быть такого не может, что б ошибку не показало.. |
| Автор: takedo 1.6.2005, 15:32 |
| бывает и Debug Assertion Failed! File: winprocc.cpp и ничего не посмотришь! Но! сначала убивается добавочный поток, потом основной, а в процессе работы(до закрытия) все нормально в edit. Я и говорю, что все было в порядке, до тех пор как не начал из потока отрисовывать. Да я вообще хотел бы просто узнать как такие вещи делают? начал бы заново, если бы знать как! Подскажите, пожалуйстаааа. Добавлено @ 15:33 когда ненормально завершается, тогда и такое бывает Detected memory leaks! Dumping objects -> {10733} normal block at 0x0032F658, 70 bytes long. Data: < C| > B8 AE 43 7C 1A 00 00 00 1A 00 00 00 01 00 00 00 {10731} normal block at 0x0032F4B0, 20 bytes long. Data: < C| > B8 AE 43 7C 01 00 00 00 01 00 00 00 01 00 00 00 thrdcore.cpp(311) : {174} client block at 0x0032F948, subtype c0, 68 bytes long. Но когда завершается без ошибок, то все нормально! |
| Автор: Coocky 1.6.2005, 15:37 | ||
takedo
http://www.firststeps.ru/dotnet/r.php?83 И далее там |
| Автор: takedo 1.6.2005, 15:38 |
| только что от туда, не помогло. |
| Автор: Coocky 1.6.2005, 15:40 | ||
Дык может поток закрываешь, когда еще ненадо закрывать? |
| Автор: takedo 1.6.2005, 15:45 |
| Можно получить ответ на такой вопрос: "Можно ли вызывать из рабочего потока функцию DrawItem объекта" типа так: DWORD Potok(LPVOID lparam) { CJpDoc = pDoc = reinterpret_cast<CJpDoc*>(lParam); if(!pDoc)return 1; if(!pDoc->IsKindOf(RUNTIME_CLASS(CJpDoc)))return 2; while(1) { pDoc->m_automats->ptr_button[1]->SetCondition(1);//или 2 или 3 .... } } CButton1 : public CButton { public BYTE cond; SetCondition(BYTE n){cond=n;GetColor(/*выбор цветов*/); Invalidate(/*вызов DrawItem*/)} } Добавлено @ 15:46 а закрываю я его в void CJpDoc::OnCloseDocument() запускаю в BOOL CJpDoc::OnNewDocument() |
| Автор: Dreamer_0x01 2.6.2005, 15:39 | ||
А вот эта хрень выдается, когда ты память не освобождаешь занятую. Как правило, это из-за того, что забываешь деструктор вызвать в каких-то крайних ситуациях. |
| Автор: takedo 4.6.2005, 14:08 |
| Сенькю вери матч! Однако, все проблемы были все-таки из за синхронизации, теперь все гуд! Но!!!!!!!!!!!!! Вот чего не понятно: приложение SDI. Когда пытаюсь убить поток, который отрисовывает в CView при закрытии фрейма(крестик справа вверху), то все виснет. Может быть фрейм посылает WM_QUIT, а мой поток WM_PAINT они друг друга пережидают??? Кто - то знает чего происходит? Я сделал по меню выход. Там убиваю поток, затем вызываю CFrameWnd::OnClose(); и все работает. Так вот ещй проблема(будете смеятся): не получается во фрейме сделать SYSMENU только с кнопками максимизировать и минимизировать и без активной кнопки закрыть!!! Кто то может объяснить как это сделать? Только сперва попробуйте сами на SDI потом уже советуйте, пожалуйста... |
| Автор: Coocky 4.6.2005, 23:19 | ||
takedo
Не виснет, а поток не завершается.Проверь, как ты закрываешь его. И вообще обработай закрытие в WM_ENDSESSION |