Автор
|
Тема: Проблема с нитью... :-(
|
bobo |
опубликован 30-08-2001 17:53 MSK
Создаю в классе нить, в качестве начального адреса которой указываю ф-ию из другого класса (эта ф-ия статическая, иначе не компилируется) - всё нормально. Но при выполнении программы эта нить после создания прекращает своё существование... В чём может быть причина? Аргументы, которые я запихнул в CreateThread() тоже static - может в этом проблема? Но если их не сделать static, то не компилируется...
|
m_fox
|
опубликован 30-08-2001 18:05 MSK
Что за изврат использовать в классах статические функции для таких целей. Гораздо безопаснее тогда сделать глобальную функцию. Чтобы не делать ее статической, делаешь глобальную, а ей передаешь указатель на объект, и запускаешь эту функцию на выполнение. Тогда ты получишь из нее доступ ко всем членам того объекта, которого нужно.Хорошо бы твой пример посмотреть. Возможно ты делаешь CloseHandle, TerminateThread вне ф-ции нити. Или выходишь из функции потока. |
bobo
|
опубликован 30-08-2001 18:49 MSK
Ни CloseThread(), ни TerminateThread я вообще не использую! А вот про ф-ию потока поясни попобробнее пожалуйста. |
m_fox
|
опубликован 30-08-2001 19:10 MSK
Завтра подробно напишу. Сейчас 2 часа ночи. спать хочу. |
bobo
|
опубликован 30-08-2001 19:12 MSK
Всё - заработало! Ф-ия, которую я нити передавал, с аргументом была... аргумент убрал - нить выполняется. |
Flex Ferrum
|
опубликован 31-08-2001 10:19 MSK
m_fox: А изврат, как ты говоришь, в том, что если ты функцию потока делаешь статическим членом класса, то тебе не надо о friend и т. п. думать. В принципе, функция потока может быть даже нестатическим членом класса (поскольку принимает один параметр, который может быть указателем на экземпляр класса). Так что, ИМХО, нет никаких причин делать функцию потока глобальной. |
m_fox
|
опубликован 31-08-2001 11:05 MSK
Ок, допустим надо создать 5 различных функций для разных задач. И предположим, что 1-я должна работать в двух экземплярах, но с разными параметрами. В случае через static нужно будет написать 6 различных классов со всеми запусками и остановами потоков, а не просто 5 различных функций. Я отправил статью, потом кину ссылку, посмотрите на мою идею, которой причем и пользовался. |
Flex Ferrum
|
опубликован 31-08-2001 11:19 MSK
Зачем такие сложности? Так или иначе, с формальной точки зрения, два потока, выполняющие разные задачи ассоциируются с различными классами и имеют различне данные. По сему, так или иначе для нового типа потока нужно создавать либо новую функцию, либо новый класс. Я остановился на втором варианте, когда создается новый класс (производный от некоего базового), перегружается виртуальная функция Run, вызывающаяся из статического метода базового класса. В итоге и волки сыты, и овцы целы. |
m_fox
|
опубликован 31-08-2001 11:24 MSK
Что значит сложности? Приходилось делать такое. А не проще-ли сделать: CCalcThread CalcThread1; CCalcThread CalcThread2; Задать просто разные значения переменным в классе и все. Будет всего один класс. |
m_fox
|
опубликован 31-08-2001 11:37 MSK
Вот адрес статьи: http://athena.vvsu.ru/~kiv/threads.htm |
Flex Ferrum
|
опубликован 31-08-2001 11:52 MSK
А можешь пояснить, какие приемущества ООП теряются при использовании статической функции потока? Помоему, как раз наоборот. Тут тебе и наследование и инкапсуляция... |
m_fox
|
опубликован 31-08-2001 12:08 MSK
Например полиморфизм. Попробуй сделать статическую ф-цию виртуальной. |
Flex Ferrum
|
опубликован 31-08-2001 12:20 MSK
Согласен, статическую функцию виртуальной ты никак не сделаешь, зато без проблем можешь вызвать виртуальную функцию из статической. Например так:int TThread::Execute(void * Param) { int ExitCode; TThread * T = (TThread *)Param; T -> Running = true; try { T -> InitInstance(); T -> ExitCode = T -> Run(); T -> ExitInstance(); ExitCode = T -> ExitCode; } catch(std :: exception& ex) { LogMessage(llError,"STL exception occured in thread: %s",ex . what()); ExitCode = -1; } catch(...) { LogMessage(llError,"Unknown exception occured in thread"); ExitCode = -1; } T -> Running = false; if(T -> m_AutoDelete) delete T; #ifdef _WIN32 return ExitCode; #else pthread_detach(T -> Thread); static int RetVal = ExitCode; pthread_exit((void *)RetVal); #endif } Где Run - это виртуальная функция, отвечающая за логику потока... |
m_fox
|
опубликован 31-08-2001 12:25 MSK
Организуй вызов: class A { int m_na; public: A(){}; virtual Func1(){m_na++}; static Func2(){[b]Func1()[\b]}; } |
Flex Ferrum
|
опубликован 31-08-2001 12:32 MSK
Не передергивай. Ты понимаешь, о чем я говорю. В моем случае статическая функция класса делает то-же самое, что глобальная ThreadProc в твоем. |
m_fox
|
опубликован 31-08-2001 16:11 MSK
Вобще-то я не совсем понял твою идею. Но хотел бы посмотреть целиком или схематично. Но в общем способ реализации на вкус производителя. Если не лень, то вышли схемотичное решение со статической функцией, можно на email. |
Flex Ferrum
|
опубликован 31-08-2001 16:51 MSK
Все достаточно просто. У тебя есть базовый класс для всех ниток: class TThread { virtual int Run() = 0; static int Execute(); public: TThread() {;} ~TThread() {;} void Start(); };void TThread :: Start() { Thread = CreateThread(NULL,0,(TThreadFunct)TThread :: Execute,this,0,NULL); } int TThread :: Execute(void * _T) { TThread * T = (TThread *)T; return T -> Run(); } В производных классах перегружаешь метод Run. И все. После чего пишешь: TMyThread Thread; Thread . Start(); В принципе, то-же самое, что и у тебя, только твоя глобальная ThreadProc сделана статической. Согласись, этот вариант чуть больше отвечает концепциям ООП. |
Flex Ferrum
|
опубликован 31-08-2001 17:01 MSK
В догонку - естественно, Run должен быть protected. |
m_fox
|
опубликован 31-08-2001 17:40 MSK
Тепрь понял. Я еще сам это покручу. Но ты знаешь, когда мы решали эту проблему, то так через static мы не догнали. Мы статик функцию передовали в качестве параметра и у нас фигня шла, как сам понимаешь.
|
Flex Ferrum
|
опубликован 31-08-2001 17:49 MSK
Фишка, на самом деле, в том, что тут можно напрямую нестатический метод передавать. Ведь каждый нестатический метод получаеи в качестве неявного параметра this (указатель на экземпляр), а функция потока получает на входе всего один параметр, и тот void * , т. е. может быть чем угодно. Так что, при большом желании, можно и без static обойтись. |
m_fox
|
опубликован 31-08-2001 18:04 MSK
Ты в какой области работаешь? Я последние пару лет занимался обработкой изображений. |
Flex Ferrum
|
опубликован 31-08-2001 23:43 MSK
В настоящее время работаю в области веб- и системного программирования, но, пока учился, занимался цифровой фотограмметрией и смежными с ней областями. |