| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C++ Builder > Проблемы при работе с несколькими потоками |
| Автор: witeman 2.8.2006, 12:37 | ||||||||
| Здравствуйте, как вы уже наверное догадались в данной теме речь пойдёт о многопотчном приложении. Перед тем как я сформулирую ошибку, я опишу вам структуру своего проекта. Вообще сейчас я пишу программу для пересылки файлов в сети будь-то телефонное соединение или же локальная сеть. На сервере выбирается файл для отправки и отправляются клиенту поток связанный с выбраннным файлом, а клиент соответственно его принимает. Сначало о принципах работы... Клиент и сервер обмениваютсяпсевдо-командами,например: при выборе файла на сервере выполняется следующий код:
А когда подключается клиент такой код:
т.е. я имею ввиду строку "!selected", котроая посылается клиенту и, вследствие этого, на клиентском выполняется обработчик события - проверяется какая команда была послана, выполняется соответсвующее действие ну и т.п. Ниже я привел обработчик события сокета сервера(для чего я все это делаю будет понятно дальше) :
"ms" - это объект класса TFileStream (его я объявил в ".h") Во время закачки у клиента отображаются проценты (Это вычисляеися простейшим арифмитическим методом пропорции: RzProgressBar1->Percent=100*Data->Size/DataSize : где Data - объект класса TFileStream, а его свойство означает сколько процентов закачено, т.е. размер файла в которого записывает поток;DataSize - размер пересылаемого файла ) А по поводу сервера я долго ломал голову как можно реализовать подчет процентов, ведь когда сокет начинает посылку потока "код блокируется". Тут мне в голову пришла идея о многопоточности. Прочитав пару раз главу из книги, я начал написать второй поток.
Все как и положено, доступ к визуальному компоненту предоставлен через Mutex и Synchronize, и код вроде бы правильный, да и что самое главное работает, если бы не одно НО! Как мы видим в функции-члене Display(), идёт обращение к другому потоку , о котором я говороил ранее (см.обработчик события сокета сервера), именно из-за этого и возникает ошибка. А конкретнее ошибке возникет из-за взаимодействия ServerSocket1->Socket->Connections[0]->SendStream(ms) и метода Synchronize. Как я пологаю во время того как один поток (я имею ввиду поток сокета) прекратил свое существование другой продолжает ссылаться на него, и использовать его данные. Все вроде-бы логично , но всё же Display() использует в вычисления поток ms, который ни какого отношения (не считая использования) к потоку сокета не имеет! Что же все-таки в итоге получается? Что два потока используют ms и, из-за синхронного обращения возникет ошибка!? Эта ошибка чаще всего появляется под конец закчки т.е. стабильно на 99%. Но это ещё не все... Иногда бывает так что посередине зкачки отлдчик выдаёт мне сообщение об ошибке, но уже иного плана "Can't canvas drawing" или что-то в этом роде (у меня нет возможности сейчас это проверить),но т.к. я использовал вовсе не канву, а визуальный компонент, причем предаставил доступ к нему правильным образом, меня это подталкивает к выводу, что ошибка всё таже.... Ну вот я и озвучил все проблемы и вопросы, которые у меня были. Готов принять практически любые предложения вплоть до модификации соката или потока; Если у кого-нибудь есть идеи как реализовать данную задачу, и вовсе без второго потока, я с радостью выслушаю предложения. Заранее благодарен. |
| Автор: witeman 4.8.2006, 10:15 |
| Товарищи, неужели ни у кого нет ни каких идей!? |
| Автор: _hunter 4.8.2006, 10:29 |
| идеи у кого-то может и есть (точнее могли бы появится при правильном вопросе), но тут много текста ни о чем. так же радуют сообщения об ошибках (точнее полное отсутсвие оного в первом случае и непонятный набор слов во втором) поэтому ограничусь стандартными советами: 1 (самый главный) -- если не можеш найти ошибку -- упрощай задачу 2 -- перед работой с указателем проверяй его валидность 3 -- проверь синхронизацию |
| Автор: witeman 4.8.2006, 11:01 | ||||||
Ага так значит
Ну это то безусловно... А по поводу
В этом собственно и весь вопрос. Как? здесь мне и нужен ваш совет,ведь я же уже и так использую Mutex, да + тут 3 потока. P.S.По поводу раздутости текста ты _hunter, отчасти прав, но мне, просто так легче сформулировать проблему, да и не будет всяких вопросов по поводу раелизации потока |
| Автор: Romikgy 4.8.2006, 11:42 |
| Я единственого не понял , как ты создаешь потоки???? Виндовыми функциями или билдера? если виндовыми то и создавай/следи за синхронизацией, если же билдаром поток создан , на кой те в мутексы лезть , создай функцию и вызови ? чего мудришь не понятно? Добавлено @ 11:44 Если хоть чуть чуть разбираешься в дельфи , то прочти это, очень пользительно http://forum.vingrad.ru/index.php?showtopic=60076 |
| Автор: witeman 4.8.2006, 12:13 | ||
Romikgy, это я уже сам запутался, Mutex здесь совсем не нужен
Но тем не менее ошибка та же остается... А за статью огоромное спасибо - просто супер |
| Автор: Romikgy 4.8.2006, 12:53 |
не мне а автору статьи! еще раз об ошибке , и плз без воды, конкретно |
| Автор: dumb 4.8.2006, 13:26 |
все обращения к компонентам vcl должны быть внутри вызываемой Synchronize процедуры. |
| Автор: witeman 4.8.2006, 14:34 | ||||||||||
В конец расстроенный гонениями типа:
(Блин я же это всё писал для того чтобы была понятна не только сама проблема,но ещё и все ньюансы Я погрузился в раздумья над своим сырцом. В конце концов понял в чем ошибка!
Я вставил блоки и сключения и !самое главноне! в catch(...) указал функцию выхода из потока Terminate(). Всё ошибка решена. Занавес... Всем спасибо за проявленный интерес к вопросу! З.Ы.:Romikgy,
|
| Автор: _hunter 4.8.2006, 14:55 |
| дык это не решение проблемы. это ее извращенное убийство... это как вырезать кусок стены чтобы прохладнее стало вместо того, чтобы открыть окно... по проблеме: у тебя есть цепочка потенциально невалидных указателей: Form1, RzProgressBar2, Percent, ms, Position, Size; ни один из них ты не проверяеш... |
| Автор: Romikgy 4.8.2006, 15:11 |
на кой это в потоке? Добавлено @ 15:12 тогда пжалста , был рад помочь |