Перейти из форума на сайт.

НовостиФайловые архивы
ПоискАктивные темыТоп лист
ПравилаКто в on-line?
Вход Забыли пароль? Первый раз на этом сайте? Регистрация
Компьютерный форум Ru.Board » Компьютеры » Прикладное программирование » CreateThread

Модерирует : ShIvADeSt

 Версия для печати • ПодписатьсяДобавить в закладки
Страницы: 1 2

Открыть новую тему     Написать ответ в эту тему

Jojobets



Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
C++ Builder.
Пытаюсь создать метод класса, в котором создается поток при помощи CreateThread на основе другого метода этого же класса (динамического). И ничего не выходит.
 
class myclass
{
public:
    __fastcall myclass();
    DWORD WINAPI method1(LPVOID);
    void __fastcall method2();
};
__fastcall myclass::myclass(){}
DWORD WINAPI myclass::method1(LPVOID)
{  
  //Что-то делаем...
  ExitThread(0);
  return 0;
}
void __fastcall myclass::method2()
{  unsigned long threadID;
   HANDLE mthread;
   mthread = CreateThread(NULL,0,method1,0,0,&threadID);
}
 
Как можно решить проблему?

Всего записей: 162 | Зарегистр. 17-01-2003 | Отправлено: 17:19 17-05-2005
mr_eoi



Silver Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Jojobets
Попробуй method1 как static, но в этом случае будет недоступен this.

----------
Per Aspera Ad Astra...

Всего записей: 2187 | Зарегистр. 10-08-2003 | Отправлено: 17:27 17-05-2005 | Исправлено: mr_eoi, 17:32 17-05-2005
WiseAlex



Софтовых дел М...
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Jojobets

Код:
 
static DWORD WINAPI method1(LPVOID);
 

Всего записей: 1001 | Зарегистр. 02-03-2003 | Отправлено: 17:29 17-05-2005 | Исправлено: WiseAlex, 17:30 17-05-2005
Jojobets



Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Насколько я понимаю, статические методы позволяют вызывать в себе только статические же другие методы, а это мне не подходит.  
Можно как-то по другому обмануть компилятор? TThread не предлагать

Всего записей: 162 | Зарегистр. 17-01-2003 | Отправлено: 17:45 17-05-2005
mr_eoi



Silver Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Jojobets
17:45 17-05-2005
Цитата:
Можно как-то по другому обмануть компилятор?

Можно, из method1 убрать LPVOID. Вместо параметра фунции будет использоваться сам this

Код:
...
DWORD WINAPI myclass::method1()
...
mthread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)method1,0,0,&threadID);


----------
Per Aspera Ad Astra...

Всего записей: 2187 | Зарегистр. 10-08-2003 | Отправлено: 17:51 17-05-2005 | Исправлено: mr_eoi, 17:58 17-05-2005
Jojobets



Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Я имел в виду другое. В качестве 3-го параметра в CreateThread должен быть указан стартовый адрес функци, которая будет выполняться в создающемся потоке. Под это определение подходит как раз имя статической функции, если можно так выразиться. Как туда подставить адрес динамического метода класса, чтоб компилятор не ругался?
 
Добавлено:
Возможно ли такое вообще, или надо искать другие решения?
 
 
Добавлено:
Member function must be called or its address taken.
Вот он что говрит про это  

Цитата:
mthread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)method1,0,0,&threadID);  


Всего записей: 162 | Зарегистр. 17-01-2003 | Отправлено: 18:23 17-05-2005
mr_eoi



Silver Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Jojobets
18:23 17-05-2005
Цитата:
Как туда подставить адрес динамического метода класса, чтоб компилятор не ругался?

А какя цель преследуется?
Если в thread необходимо поработать с членами класса можно сделать так:

Код:
 
DWORD MyClassThunk(LPVOID ptr);
...
class myclass {
public:
DWORD __fastcall method1(LPVOID)
{
 ...
}
void __fastcall method2()  
{  unsigned long threadID;  
   HANDLE mthread;  
   mthread = CreateThread(NULL,0,MyClassThunk,(LPVOID)this,0,&threadID);  
}  
};
 
DWORD MyClassThunk(LPVOID ptr)
{
   myclass *cls = (myclass*)ptr;
   return cls->method1();
}
 
 


----------
Per Aspera Ad Astra...

Всего записей: 2187 | Зарегистр. 10-08-2003 | Отправлено: 19:34 17-05-2005 | Исправлено: mr_eoi, 19:35 17-05-2005
Jojobets



Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Цель преследуется такая: есть метод (или функция), адрес которого нужно подставить в createthread для создания потока. При этом, в этом методе вызываются другие методы класса.  
Допустим, есть методы (нестатические) класса myclass: method1(), method2(), method3().
Также есть метод(-ы) этого класса method_х(), в котором все эти методы вызываются.  
Возможно ли в одном из методов класса, допустим, method_5(), при помощи createthread создать поток, в котором будет выполняться method_х() ?
 
 
 

Всего записей: 162 | Зарегистр. 17-01-2003 | Отправлено: 20:12 17-05-2005
StatujaLeha

Newbie
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
глян сюда, может поможет или какие новые идеи подскажет http://forums.realcoding.net/index.php?showtopic=5936

Всего записей: 20 | Зарегистр. 11-04-2005 | Отправлено: 21:18 17-05-2005
mr_eoi



Silver Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Jojobets
Ну и чем тебе предложенная реализация не нравится?
Sorry забыл:
Код:
DWORD WINAPI MyClassThunk(LPVOID ptr);
Можешь лепить методов до посинения и вызывать их один из другого. Причём, обрати внимание: все методы не статические.

----------
Per Aspera Ad Astra...

Всего записей: 2187 | Зарегистр. 10-08-2003 | Отправлено: 21:49 17-05-2005 | Исправлено: mr_eoi, 21:50 17-05-2005
Jojobets



Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору

Цитата:
Ну и чем тебе предложенная реализация не нравится?  

Не нравится, потому что она нерабочая.
Компилятор ругается на строчку
cls->method1();  
 
"member function must be called, or its address must be taken"

Всего записей: 162 | Зарегистр. 17-01-2003 | Отправлено: 16:11 18-05-2005
WiseAlex



Софтовых дел М...
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Jojobets

Цитата:
Не нравится, потому что она нерабочая.

сильно подмывает прокомментировать про руки, но не буду.
приведи кратко что у тебя написано, скорее всего делаешь что-то неверно, т.к. предложенный вариант проверен и 100% рабочий - именно он используется и в TThread и в других реализациях типа mfc

Всего записей: 1001 | Зарегистр. 02-03-2003 | Отправлено: 22:01 18-05-2005
Arion



Full Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Я решал данную проблему с помощью friend функции. Она не является членом класса, поэтому ее адрес можно передавать CreateThread (хотя, я предпочитаю _beginthreadex), с другой стороны - она может пользоваться всеми методами и свойствами класса. Выглядело это все как то так:

Код:
 
typedef unsigned (__stdcall *PTHREAD)(void*);
class CMyClass
{
public:
DWORD WINAPI _tMyClassMethodThread(PVOID pvContext);
friend DWORD WINAPI _tInnerThread(PVOID pvContext);
void Start();
};
 
//Realization
DWORD WINAPI _tInnerThread(PVOID pvContext)
{
CMyClass* pClass = static_cast<CMyClass*>(pvContext);
return(pClass->_tMyClassMethodThread(pvContext));
}
 
DWORD WINAPI CMyClass::_tMyClassMethodThread(PVOID pvContext)
{
//...
}
 
void CMyClass::Start()
{
//...
HANDLE hThread = (HANDLE)_beginthreadex(...,(PTHREAD)_tInnerThread,this,...);
//...
}
 
 
 

Всего записей: 436 | Зарегистр. 29-06-2003 | Отправлено: 07:21 19-05-2005 | Исправлено: Arion, 07:22 19-05-2005
mr_eoi



Silver Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Jojobets
16:11 18-05-2005
Цитата:
Компилятор ругается на строчку  
cls->method1();  

Sorry, у меня ошибочка, надо писать  

Код:
DWORD __fastcall method1(void)
 
Скопировал у тебя, а поправить забыл  
 
Добавлено:
Arion
Как не крути, а _tInnerThread надо объявлять статической.
static_cast<CMyClass*> эквивалентно (CMyClass*)

----------
Per Aspera Ad Astra...

Всего записей: 2187 | Зарегистр. 10-08-2003 | Отправлено: 07:35 19-05-2005 | Исправлено: mr_eoi, 08:06 19-05-2005
Arion



Full Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору

Цитата:
Как не крути, а _tInnerThread надо объявлять статической.  

Это с чего бы то? У меня вполне нормально работало и так.

Цитата:
static_cast<CMyClass*> эквивалентно (CMyClass*)

Знаю, опять таки и что с того?

Всего записей: 436 | Зарегистр. 29-06-2003 | Отправлено: 12:00 19-05-2005
Duke Shadow



Silver Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
mr_eoi

Цитата:
static_cast<CMyClass*> эквивалентно (CMyClass*)

А не reinterpret_cast<CMyClass*> ли?

----------
Тот, кто умеет - делает, кто не умеет - учит(с)Б. Шоу
Войны никого не могут сделать великим(с)магистр Йода
Аватар(c)MindDiver

Всего записей: 3912 | Зарегистр. 15-02-2003 | Отправлено: 12:03 19-05-2005
mr_eoi



Silver Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Duke Shadow
12:03 19-05-2005
Цитата:
А не reinterpret_cast<CMyClass*> ли?

Думаю для указателей - всё равно. Для всего остального - конечно нет (в смысле не всё равно).

----------
Per Aspera Ad Astra...

Всего записей: 2187 | Зарегистр. 10-08-2003 | Отправлено: 12:26 19-05-2005
vserd

Silver Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Вот код на Delphi. Я думаю что в Билдере тоже сработает.
У меня он работает именно с потоками.
unit FunctionWrapper;
 
interface
{Обработка обратных вызовов OC Windows методами классов.}
{http://mazurkin.virtualave.net/papers/11callback/}
{Можно использовать при создании потоков, таймеров, окон и др. случаях.
 !!! Метод или функция должны быть объявлены как StdCall, иначе не будет работать. !!! }
 
function CreateFunctionWrapper(Obj: TObject; Method: Pointer): Pointer;
procedure DeleteFunctionWrapper(Wrapper: Pointer);
 
{пример использования:
 type
   TMyClass = class
   Private
     FWindows    : TStringList;
     FHandler : Pointer;
     function EnumWindowsCallback(Wnd: THandle; Param: Cardinal): LongBool; StdCall;
   public
     procedure Refresh;
     constructor Create;
     Destructor Destroy; override;
   end;
 
 constructor TMyClass.Create
 begin
  ......
  // Создаем wrapper для метода обратного вызова
  FHandler := CreateFunctionWrapper(Self, @TMyClass.EnumWindowsCallback);
  .....
 end;
 
 Destructor TMyClass.Destroy;
 begin
   .....
   DeleteFunctionWrapper(FHandler);
   ....
 end;
 
 function TMyClass.EnumWindowsCallback(Wnd: THandle; Param: Cardinal): LongBool;
 var WindowName : array [0..1023] of Char;
 begin
   // Получаем имя окна
   GetWindowText(Wnd, @WindowName[0], SizeOf(WindowName));
   // Добавляем имя окна в коллекцию
   if WindowName <> '' then FWindows.Add(WindowName);
   // Продолжаем перечисление
   Result := True;
 end;
 
 procedure TMyClass.Refresh;
 begin
   // Очистка контейнера
   FWindows.Clear;
   // Перечисляем окна
   EnumWindows(FHandler, 0);
   // Сортируем названия
   FWindows.Sort;
 end;
}
{Функция обратного вызова, оформленная в виде метода класса имеет полный доступ
 ко всем членам класса. При этом второй параметр функции не задействован и мы
 можем использовать его для своих нужд}
 
implementation
uses Windows;
 
function CreateFunctionWrapper(Obj: TObject; Method: Pointer): Pointer;
begin
  // Allocate the callback block
  Result := VirtualAlloc(nil, 128, MEM_RESERVE OR MEM_COMMIT, PAGE_EXECUTE_READWRITE);
  // Check allocated block
  Assert(Result <> nil, '{9FA7DAE8-0FA4-4223-8230-8CA14DAAF451}');
  // Compose the callback block
  asm
    mov  EAX, Obj
    mov  ECX, Result
    mov  word  ptr [ECX+0], $6858               // pop  EAX
    mov  dword ptr [ECX+2], EAX                 // push _Self_
    mov  word  ptr [ECX+6], $E950               // push EAX
    mov  EAX, Method
    sub  EAX, ECX
    sub  EAX, 12
    mov  dword ptr [ECX+8], EAX                 // jmp  Object.Method
  end;
end;
 
////////////////////////////////////////////////////////////////////////////////
// Delete the wrapper
////////////////////////////////////////////////////////////////////////////////
procedure DeleteFunctionWrapper(Wrapper: Pointer);
begin
  VirtualFree(Wrapper, 0, MEM_RELEASE);
end;
 
end.

Всего записей: 2065 | Зарегистр. 08-05-2002 | Отправлено: 12:51 20-05-2005
informesrab

Newbie
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Написал в Delphi процедуру которая ожидает несколько секунд, а потом выводит изображение.
 
var a1,a2:integer;
begin
  a2:=1;
  for a1:=1 to 5 do
  begin
      sllep(4500);
      a2:=a2+1;
      edit1.text=inttostr(a2);
      form1.refresh;
  end;
end
 
Работает она нормально, но если сернуть окно а потом развернуть то значение в edit1 не изменяеться и процедура доходит до конца,  если не сворачивать то все работает нормально. Есть ли другие функции для обновления изображения.

Всего записей: 17 | Зарегистр. 16-06-2007 | Отправлено: 12:42 18-10-2007 | Исправлено: informesrab, 12:52 18-10-2007
oan42



Full Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
informesrab
Попробуйте Edit1.Invalidate;

Всего записей: 488 | Зарегистр. 03-08-2004 | Отправлено: 22:45 18-10-2007
Открыть новую тему     Написать ответ в эту тему

Страницы: 1 2

Компьютерный форум Ru.Board » Компьютеры » Прикладное программирование » CreateThread


Реклама на форуме Ru.Board.

Powered by Ikonboard "v2.1.7b" © 2000 Ikonboard.com
Modified by Ru.B0ard
© Ru.B0ard 2000-2024

BitCoin: 1NGG1chHtUvrtEqjeerQCKDMUi6S6CG4iC

Рейтинг.ru