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

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

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

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

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

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
SHANDLE

Advanced Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Компилятор правильно ругается, потому что пишите маразм.
 
Вариант 1
void Func1()
{
  myclass mc;
  mc.CreateThreadMethod();
}
 
В этом случае экземпляр myclass (переменные-члены) находится в стеке первого потока.
Что будет делать второй поток с данными стека первого потока? Если просто читать, то ничего, кроме мусора, он оттуда не вытянет. А если решиться что то записать, то испоганит стек первого потока, и первый поток благополучно сдохнет.  
 
Вариант 2
void Func2()
{
  myclass *pmc = new myclass;
  pmc->CreateThreadMethod();
}
 
Теперь экземпляр класса не в стеке. Но нужно будет не забыть удалить его. Тогда проще написать так (без идиотской идеи запускать метод класса отдельным потоком):
 
DWORD WINAPI MyclassThunk(LPVOID lpObj)
{
  myclass *pmc = (myclass*)lpObj;
  pmc->PublicMethod_1();
  pmc->PublicMethod_2();
//  .....
  pmc->PublicMethod_N();
  delete pmc;
  return 0;
}
 
void Func3()
{
  myclass *pmc = new myclass;
  if (pmc)
  {
    HANDLE hThread = CreateThread(0,0,MyclassThunk, pmc, CREATE_SUSPENDED, 0);
    if (!hThread)
    {
      delete pmc;
    }
    else
    {
      ResumeThread(hThread);
      CloseHandle(hThread);
    }
  }
}
 
 

Всего записей: 928 | Зарегистр. 19-01-2007 | Отправлено: 04:52 09-12-2007 | Исправлено: SHANDLE, 04:56 09-12-2007
delover

Advanced Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Тут видимо проблемма с идеологией потоков. Какая собстьв разница для реализации Си я ещё не понимаю. Дело в том, что когда создаётся объект потока, он может запускаться сразу, а может и CREATE_SUSPENDED. Я всегда делаю SUSPENDED так как всегда надо перед работой объекта потока заполнить его поля (члены) (простите за паскаль).
 
My:=TMyThread.Create({suspended}true);
My.FreeOnTerminate:=True;
My.OnDestroy:=DefaultDestr;
My.IterationFunc1:=@Func1;
My.IterationFunc2:=@Func2;
...
My.Scenario:=TMyScenatio1.Create;
My.ProgressBar:=Bar1;
My.Resume;
 
Только так можно реально работать с потоками без проблем. В потоках есть возможность работы без suspended/Resume, но это сделано исключительно для возможности защиты от взломов. Больше этого не надо нигде. А нормально это когда вместе с созданием форм создаются потоки которые вообще My.FreeOnTerminate:=False. Нафига освобождать память при выходе если приложение эту память всё равно освободит? Но когда уже формы созданы и поля заполнены, то перед Application.Run все потоки резюмируются и начинают работать в среде, когда главные формы уже созданы - и никакой мороки. Кучу раз наблюдал исходники, когда эти правила игнорируются и работает всё криво. Но когда чуть чуть навести макияж, то всё начинает пахать как часы.

Всего записей: 1395 | Зарегистр. 25-06-2007 | Отправлено: 19:51 10-12-2007
Открыть новую тему     Написать ответ в эту тему

Страницы: 1 2

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


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

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

BitCoin: 1NGG1chHtUvrtEqjeerQCKDMUi6S6CG4iC

Рейтинг.ru