eXeL@B —› Программирование —› Delphi, class, ошибка доступа к private из thread, помогите разобраться. |
Посл.ответ | Сообщение |
|
Создано: 23 октября 2009 15:41 · Личное сообщение · #1 Помогите разобраться с проблемой. На примере это выглядит так: Code:
После вызова Test падает в треде на доступе к text. Задача требует именно создание треда в котором будет вызвана процедура работающая со строкой text. Если из треда вызывать процедуру которая обращается к text, то падает на обращении в этой процедуре. |
|
Создано: 23 октября 2009 17:11 · Личное сообщение · #2 |
|
Создано: 23 октября 2009 18:18 · Поправил: ToBad · Личное сообщение · #3 Немного модифицировал тут: Code:
Вызываю так: Code:
Archer пишет: Есть подозрение, что члены класса вызываются через указатель на класс, которого у потока нет. Да, буду смотреть под отладчиком. То, что пальцем в небо указывает, а не на строку и так понятно, вопрос в другом, как написать правильно, что бы обойти эту проблему. Если в двух словах, то это всё делаю для обхода известной проблемы с InternetReadFile, которая не имеет таймаута и в случае отсутствия инета зависает довольно на долго. По этому планирую вызывать это в треде и задавать таймаут через WaitForSingleObject. Зачем полез создавать класс, сам уже не знаю, без него всё работало нормально... Но раз уж начал, хотел бы побороть проблему... 2987_23.10.2009_CRACKLAB.rU.tgz - test.exe |
|
Создано: 23 октября 2009 18:29 · Поправил: Модератор · Личное сообщение · #4 ToBad пишет: которая не имеет таймаута и в случае отсутствия инета зависает довольно на долго. а как же: Code:
----- [nice coder and reverser] |
|
Создано: 23 октября 2009 19:17 · Поправил: [wl] · Личное сообщение · #5 Если решать именно исходную проблему, то примерно так: CreateThread кажется принимает одним из параметров произвольный указатель. Нужно при создании потока передать Self, а в функции потока привести этот указатель к TStatistic и уже через него обращаться к тексту. и вообще, как-то криво поток создается, фунция потока должна иметь такой прототип (судя по MSDN): DWORD WINAPI ThreadProc( [in] LPVOID lpParameter ); а не void proc(); как в твоем случае. Хотя... раз твоя функция не статическая, то один параметр у неё похоже будет (указатель на класс), куда на самом деле будет передан 0. |
|
Создано: 23 октября 2009 19:24 · Личное сообщение · #6 |
|
Создано: 23 октября 2009 20:45 · Личное сообщение · #7 ToBad Раз работаете в Дельфиях, то желательно использовать их классы, а именно - TThread Замечание - если в коде потока надо обращаться к ГУИ - используем Synchronize() Отличный пример работы с TThread можно найти в подкаталоге Demos\Threads каталога, куда Вы установили Borland Delphi. еще можно в нете почитать, например - Первые шаги с TThread в Delphi www.realcoding.net/article/view/158 |
|
Создано: 23 октября 2009 20:49 · Личное сообщение · #8 Hellspawn пишет: а как же: Code: timeout := 10 * 1000; // 10 sec InternetSetOptionA(pInet,INTERNET_OPTION_CONNECT_TIMEOUT,@timeout, 4); InternetSetOptionA(pInet,INTERNET_OPTION_RECEIVE_TIMEOUT,@timeout, 4); InternetSetOptionA(pInet,INTERNET_OPTION_SEND_TIMEOUT,@timeout,4); К сожалению не работает так как должно. Причем не у меня одного... [wl] пишет: и вообще, как-то криво поток создается, фунция потока должна иметь такой прототип (судя по MSDN): DWORD WINAPI ThreadProc( [in] LPVOID lpParameter ); Переделаю и попробую параметр передавать. _ruzmaz_ пишет: Если text объявить как class var, то адрес строки нормально передается. Только вот у мну даже первый бокс не всегда вылазит Это как? Покажи пожалуйста примерчик. |
|
Создано: 23 октября 2009 20:55 · Поправил: _ruzmaz_ · Личное сообщение · #9 |
|
Создано: 23 октября 2009 20:59 · Личное сообщение · #10 sendersu пишет: Раз работаете в Дельфиях, то желательно использовать их классы, а именно - TThread Замечание - если в коде потока надо обращаться к ГУИ - используем Synchronize() В длл с этим классом возникали проблемы, вот тут об этом говорил. Как потом почитал, есть какие то проблемы с синхронизацией в случае с длл... А вообще мне тред нужен только для того, что бы поставить таймаут на выполнение функции работа которой может затянуться на долго. В случае использования TThread даже не знаю как это реализовать. |
|
Создано: 23 октября 2009 21:05 · Личное сообщение · #11 _ruzmaz_ пишет: class var text: string; Там же где у меня сейчас написано? Дельфи говорит что ошибка: PROCEDURE or FUNCTION expected. А вообще если пишу var text: string; после implementation, то работает, и извне недоступно. А зачем вообще это писать в привате если переменная только для внутреннего пользования? |
|
Создано: 23 октября 2009 21:11 · Личное сообщение · #12 |
|
Создано: 23 октября 2009 21:31 · Поправил: ToBad · Личное сообщение · #13 _ruzmaz_ пишет: У меня ничего не говорит (Delphi 2006). У меня Delphi 7.0... [wl] пишет: CreateThread кажется принимает одним из параметров произвольный указатель. Нужно при создании потока передать Self, а в функции потока привести этот указатель к TStatistic и уже через него обращаться к тексту. Self передал, а как привести этот указатель к TStatistic что бы обращаться к text? И получается это нужно будет передавать дальше каждой вызываемой функции? Дело в том, что такая конструкция тоже не работает правильно: Code:
|
|
Создано: 23 октября 2009 22:25 · Личное сообщение · #14 ToBad пишет: Дельфи говорит что ошибка: PROCEDURE or FUNCTION expected. Да, посмотрел в Delphi 7.0 - не работает, видимо позже добавили. ToBad пишет: А вообще если пишу var text: string; после implementation, то работает, и извне недоступно. И так можно, но я думал что тебе нужно было чтоб text не выходила за пределы класса. |
|
Создано: 23 октября 2009 22:45 · Личное сообщение · #15 приведение из одного типа в другой примерно так: Function TStatistic.ThreadFunc(x:dword):dword; stdcall; begin TStatictic(x).text end; Но работать это не будет мне кажется, так как ThreadFunc объявлена как нестатическая функция класса, то есть компилятор втихаря подставит лишний аргумент - указатель на Self: Function TStatistic.ThreadFunc(Self: TStatistic, x:dword):dword; stdcall; а нельзя никак эту функцию потока вынести из класса, чтобы не было параметра Self? |
|
Создано: 24 октября 2009 11:05 · Личное сообщение · #16 Во-первых, меняем showmessage('Это сообщение будет выдано.'); showmessage(text); // Тут падает с ошибкой. на messagebox(0,'Это сообщение будет выдано.','q',0); messagebox(0,pchar(text),'q',0); // Тут ничего не падает затем меняем CreateThread(nil,0,@TStatistic.ThreadFunc,nil,0,ThID); на CreateThread(nil,0,@TStatistic.ThreadFunc,self,0,ThID); После этого всё работает. Как тут уже сказали, в ThreadFunc неявно передаётся параметр self, но он там, собственно, и ожидается )) |
|
Создано: 24 октября 2009 12:32 · Личное сообщение · #17 Большое спасибо всем, кто отписался в теме, принял участие и помог!!! Nowar пишет: После этого всё работает. Посмотри код на 2 поста выше твоего. Вчера всё это пробовал и не работало, но сегодня прочитав такую уверенность в твоём посте попробовал ещё раз и теперь работает... Понимаю, что звучит бредово... Вот привожу полностью код который получился, может кому сгодится, нормального примера в инете не нашёл, лишь общие намёки, вывел процедурку PageToStr через которую получаю страничку в строку, конечно не нравится момент с буфером, нужно по умному сделать будет, но код писался под конкретную задачу, а в ней это допустимо. Code:
Вот я одного не пойму, зачем это делать классом? Может проще и лучше простой юнит? На конкретно этом примере есть недостатки или преимущества? Может кто нибудь в двух словах объяснить? |
|
Создано: 24 октября 2009 16:01 · Личное сообщение · #18 |
|
Создано: 24 октября 2009 16:30 · Личное сообщение · #19 |
|
Создано: 26 октября 2009 16:14 · Личное сообщение · #20 если интересно, то данная проблема есть одно из проявлений того, что VCL НЕ thread safe. а именно, showMessage в глубине себя создает форму, что НЕЛЬЗЯ делать из потока. да, МОЖЕТ прокатить. но с вероятностью 50% - подвиснет,свалится и тд. посему надобно практически всегда использовать synchronize, если есть обращение к VCL... сорри,ежели баян. |
|
Создано: 30 октября 2009 19:30 · Личное сообщение · #21 |
eXeL@B —› Программирование —› Delphi, class, ошибка доступа к private из thread, помогите разобраться. |