Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Работа с потоками вызов из потока процедур определенных вне его


Страницы:   1 2

Вова ©   (2013-06-02 21:23:00) 

Есть класс TThread. И есть некоторые функции объявленные вне этого класса (т.е. вообще не в классе). Вопрос - что происходит, когда я вызываю их из TThread(т.е. в одной из процедур этого класса)? В частности интересуют, выполняются ли они прямо в этом же потоке, или они выполняются на стороне основного потока?


Вова   (2013-06-06 00:45:00) [1]


> Далее, ReleaseDC применяется только для GetDC и GetWindowDC.
>
> Вместо нее используй DeleteDC, ты ж создаешь контекст а
> не заимствуешь.


о, спасибо.


Rouse_   (2013-06-05 23:51:00) [2]


> А DeleteObject(hBmp); еще быстрее вылетает, хотя вообще
> вот я не понял, а DeleteObject(hBmp); тут вообще нужно?
> или память освободится, когда tbmp.free сделаешь?

Освободится при разрушении класса (в твоей реализации), стало быть лишний вызов избыточен.


Rouse_   (2013-06-05 23:44:00) [3]

Учится это хорошо, тем более оптимизации, но:
Пять GDI хэндлов в минус в MyGetPixel:
hGDC := GetDC(0);
Bitp := GetDeviceCaps(hGDC, BITSPIXEL);
hTmpDC := CreateCompatibleDC(hGDC);
hTmpBmp := CreateCompatibleBitmap(hGDC, 1, 1);
SelectObject(hTmpDC, hTmpBmp);


Это еще один в Button8Click
SelectObject(HDC1, hBmp);

Далее, ReleaseDC применяется только для GetDC и GetWindowDC.
Вместо нее используй DeleteDC, ты ж создаешь контекст а не заимствуешь.

Если вся эта бета в WM_PAINT-е крутится, поломаешь систему.


Вова   (2013-06-05 23:30:00) [4]



 hSrcDC := CreateDC('DISPLAY', Nil, nil, nil);
 hDc1   := CreateCompatibleDC(hSrcDC);
hBmp   := CreateCompatibleBitmap(hSrcDC, tbmp.Width, tbmp.Height);
SelectObject(hDc1, hBmp);
BitBlt(hDc1, 0, 0, tbmp.Width, tbmp.Height, hSrcDC, tmpCoord.x1work, tmpCoord.y1work, SRCCOPY);

 tbmp.Handle      := hBmp;
 tbmp.PixelFormat := pf24bit;
 //tBmp.SaveToFile('D:\test.bmp');
 //hBmp := nil;
 //DeleteObject(hBmp);
 ReleaseDC(0, hDc1);
 ReleaseDC(0, hSrcDC);


кроме того подобные конструкции, несмотря на то, что говорят, что контекст устройства доступен только в том потоке, в котором он создан, приводят к тому, что через несколько тысяч операций ReleaseDC(0, hDc1); вылетает по ошибке. А DeleteObject(hBmp); еще быстрее вылетает, хотя вообще вот я не понял, а DeleteObject(hBmp); тут вообще нужно? или память освободится, когда tbmp.free сделаешь?


Вова   (2013-06-05 23:19:00) [5]

никогда не позно учится ) последняя функция не моя.

На самом деле я изучаю предложение перейти на HBitmap. И вот что я выяснил:

Function MyGetPixel(x, y: integer): COLORREF;
// на входе хэндл нужного окна и координаты x,y
// COLORREF pixel;
// BITMAPINFO BMI={0};
var
 hGDC: HDC;
 Bitp: integer;
 hTmpDC: HDC;
 hTmpBmp: HBITMAP;
 TMP: integer;
 pixel: COLORREF;
 BMI: BITMAPINFO;
 T: cardinal;
 i:Integer;
begin
 hGDC := GetDC(0);
 Bitp := GetDeviceCaps(hGDC, BITSPIXEL);
 hTmpDC := CreateCompatibleDC(hGDC);
 hTmpBmp := CreateCompatibleBitmap(hGDC, 1, 1);
 SelectObject(hTmpDC, hTmpBmp);
 BitBlt(hTmpDC, 0, 0, 1, 1, hGDC, x, y, SRCCOPY);

 BMI.bmiHeader.biSize := sizeof(BMI.bmiHeader);
 BMI.bmiHeader.biWidth := 1;
 BMI.bmiHeader.biHeight := 1;
 BMI.bmiHeader.biPlanes := 1;
 BMI.bmiHeader.biBitCount := Bitp;
 BMI.bmiHeader.biCompression := BI_RGB;
 BMI.bmiHeader.biSizeImage := Bitp div 8;
 BMI.bmiHeader.biClrUsed := 0;
 BMI.bmiHeader.biClrImportant := 0;

 pixel := $FFFFFF;

 i := 0;
 T := GetTickCount;
 while i < 1 do
 begin

   for y := 0 to screen.Height - 1 do
   begin
     for x := 0 to screen.Width - 1 do
     begin
      TMP:=GetDIBits(hTmpDC,hTmpBmp,0,1,@pixel,BMI, DIB_RGB_COLORS);

     end;
   end;
   inc(i);
 end;
 T := GetTickCount - T;
 ShowMessage('Время на My Функции ' + IntToStr(T));

 //TMP = GetDIBits(hTmpDC, hTmpBmp, 0, 1, &pixel, &BMI, DIB_RGB_COLORS);
 //pixel & = 0 xFFFFFF;
 // ReleaseDC(hGame,hGDC);
 result := pixel;
end;

procedure TSDIAppForm.Button8Click(Sender: TObject);
var
 HDC1: HDC;
 hSrcDC: HDC;
 hBmp: HBITMAP;
 x, y, i: integer;
 R: TRect;
 T: cardinal;
 tBmp: TBitmap;
 QP: TQuickPixels;
 Pixel1: cardinal;
begin

 R := Rect(0, 0, screen.Width, screen.Height);

 hSrcDC := CreateDC('DISPLAY', Nil, nil, nil);
 HDC1 := CreateCompatibleDC(hSrcDC);
 hBmp := CreateCompatibleBitmap(hSrcDC, R.Width, R.Height);

 SelectObject(HDC1, hBmp);
 BitBlt(HDC1, 0, 0, R.Width, R.Height, hSrcDC, 0, 0, SRCCOPY);
 i := 0;
 T := GetTickCount;
 while i < 1 do
 begin

   for y := 0 to R.Height - 1 do
   begin
     for x := 0 to R.Width - 1 do
     begin
       GetPixel(HDC1, x, y);

     end;
   end;
   inc(i);
 end;
 T := GetTickCount - T;
 ShowMessage('Время на АПИ Функции ' + IntToStr(T));

 // DeleteObject(hBmp);
 // ReleaseDC(0, HDC1);
 // ReleaseDC(0, hSrcDC);

 tBmp := TBitmap.Create;
 tBmp.Width := R.Right - R.Left;
 tBmp.Height := R.Bottom - R.Top;
 tBmp.Handle := hBmp;
 tBmp.PixelFormat := pf24bit;

 i := 0;
 T := GetTickCount;
 while i < 1 do
 begin

   QP := TQuickPixels.Create;
   QP.Attach(tBmp);

   for y := 0 to QP.Height - 1 do
   begin
     for x := 0 to QP.Width - 1 do
     begin
       Pixel1 := QP.GetPixels24(x, y);
     end;
   end;
   inc(i);
 end;
 T := GetTickCount - T;
 ShowMessage('Время на Q ' + IntToStr(T));

 QP.Free;
 tBmp.Free;
 DeleteObject(hBmp);
 ReleaseDC(0, HDC1);
 ReleaseDC(0, hSrcDC);
 // tbmp.Canvas.Unlock;

 MyGetPixel(100, 100);

end;



Да я в курсе что там куча объектов не освобождается, но я просто пытался замерить скорость и получилось, что:

АПИ GetPixel отрабатывает за 2400

QUPixel за от 0 до 15, что как бы намекает, что  реально даже засеч время не удается на таком объеме.

Ну и вот эта функция которую я переводил больше 3000

Таким образом имеем, что не QU варианты работают просто чудовищно долго, даже ScanLine только на 30% медленнее купикселей. А купиксели заточены на TBitmap..... как их переделать я ессно не знаю пока что.

Так что продолжаю мучать Tбитмап в потоке.....


Rouse_   (2013-06-05 22:42:00) [6]

А вообще ты зря этим занялся. У тебя при работе с GDI API ляп на ляпе. Сожрешь все 65535 хэндлов доступные системе - пользователи тебе спасибо не скажут :)


Rouse_   (2013-06-05 22:40:00) [7]

pixel := $FFFFFF;
TMP=GetDIBits(hTmpDC,hTmpBmp,0,1,@pixel,BMI, DIB_RGB_COLORS);


Вова   (2013-06-05 22:29:00) [8]


Function MyGetPixel(x,y:integer):COLORREF;//на входе хэндл нужного окна и координаты x,y
   //COLORREF pixel;
   //BITMAPINFO BMI={0};
var
 hGDC:HDC;
 Bitp:integer;
 hTmpDC:HDC;
 hTmpBmp:HBITMAP;
 TMP:integer;
 pixel:COLORREF;
 BMI: BITMAPINFO;

begin
   hGDC=GetDC(0);
   Bitp=GetDeviceCaps(hGDC, BITSPIXEL);
   hTmpDC=CreateCompatibleDC(hGDC);
   hTmpBmp=CreateCompatibleBitmap(hGDC,1,1);
   SelectObject(hTmpDC,hTmpBmp);
   BitBlt(hTmpDC,0,0,1,1,hGDC,x,y,SRCCOPY);

   BMI.bmiHeader.biSize = sizeof(BMI.bmiHeader);
       BMI.bmiHeader.biWidth = 1;
       BMI.bmiHeader.biHeight = 1;
       BMI.bmiHeader.biPlanes = 1;
       BMI.bmiHeader.biBitCount = Bitp;
       BMI.bmiHeader.biCompression = BI_RGB;
   BMI.bmiHeader.biSizeImage=Bitp/8;
   BMI.bmiHeader.biClrUsed = 0;
   BMI.bmiHeader.biClrImportant = 0;
   TMP=GetDIBits(hTmpDC,hTmpBmp,0,1,&pixel,&BMI, DIB_RGB_COLORS);
   pixel&=0xFFFFFF;
   //ReleaseDC(hGame,hGDC);
   result:= pixel;
end;


Помогите перевести с с++ на русский. Вообщем то я все перевел, но с указателями чет запутался

TMP=GetDIBits(hTmpDC,hTmpBmp,0,1,&pixel,&BMI, DIB_RGB_COLORS);
pixel&=0xFFFFFF; и вот это не могу перевести


Eraser   (2013-06-04 20:40:00) [9]


> Вова   (03.06.13 21:11) [11]
> объекты для работы с графикой являются потокобезопасными.
>  Это такие классы, как TFont, TPen, TBrush, TBitmap, TDrawing
> и TIcon;
>
> Graphics объекты потоко-безопасны.

это заблуждение, есть несколько узких мест, которые приводят к ошибкам, вплоть до краха приложения, если эти места не учесть. см. FreeMemoryContexts и все что с этим связано, вообще крайне тупо сделано, и не правят.


Вова   (2013-06-04 17:58:00) [10]


> покажи в своем коде "методы Lock() и Unlock()"...???если
> уж споришь и приводишь цитаты, то хоть сам их прочитай вдумчиво.
> ..  чем это противоречит сказанному выше? p.s. встроенные(/предусмотренные
> для) методы синхронизации не делают объект потокобезопасным.
> .. особенно если их вообще не использовать. (а использовать
> то будет очередь, про что выше и сказано )


Та я не спорю, просто привел цитаты, которые в инете нашел.
Если очередь не будет завязана на основном потоке, то это приемлемо. Т.к. если я начну обращаться в основной поток, у меня точно будут взаимные локи. Я этого и хотел избежать изначально. И к тому же основной процесс итак загружен, очередь будет долго обрабатываться.

Как меня спасет Hbitmap я не понял, кроме того я не знаю как обрабатывать картинки без TBitmap, т.к. даже купиксели заточены на него и как то через палитру работают.

Вообщем есть пару идей, надо попробовать..


sniknik   (2013-06-04 09:48:00) [11]

Вова   (03.06.13 21:11) [11]
покажи в своем коде "методы Lock() и Unlock()"...???

если уж споришь и приводишь цитаты, то хоть сам их прочитай вдумчиво...  чем это противоречит сказанному выше?

p.s. встроенные(/предусмотренные для) методы синхронизации не делают объект потокобезопасным... особенно если их вообще не использовать. (а использовать то будет очередь, про что выше и сказано )


Вова   (2013-06-04 01:29:00) [12]


Procedure getScreen(var tbmp: Tbitmap; tmpCoord: TCoord);
var
 hDC1: HDC;
 hBmp: HBITMAP;
 R: TRect;
begin

 if tmpCoord.x2work = 0 then
   tmpCoord.x2work := screen.Width;

 if tmpCoord.y2work = 0 then
   tmpCoord.y2work := screen.Height;

 R := Rect(tmpCoord.x1work, tmpCoord.y1work, tmpCoord.x2work,
   tmpCoord.y2work);

 tbmp             := Tbitmap.Create;
 tbmp.Width       := R.Right - R.Left;
 tbmp.Height      := R.Bottom - R.Top;
 hDc1 := CreateCompatibleDC(0);
hBmp := CreateCompatibleBitmap(GetDC(0), tbmp.Width, tbmp.Height);
SelectObject(hDc1, hBmp);
BitBlt(hDc1, 0, 0, tbmp.Width, tbmp.Height, GetDC(0), tmpCoord.x1work, tmpCoord.y1work, SRCCOPY);

 tbmp.Handle := hBmp;
 tbmp.PixelFormat := pf24bit;

 DeleteObject(hBmp);
 ReleaseDC(0, hDc1);

end;


Попробовал скринить так, вроде как канва не задействована с ее лок, анлок. А рисование и чтение сделано на UQPixels, там тоже без канвы (потому и tbitmap (( ). Но работало оно работало и вдруг вылетелело на DeleteObject(hBmp); из за неверного параметра. стало быть другой поток постарался?


Rouse_   (2013-06-03 23:16:00) [13]


> Вова   (03.06.13 01:12) [4]
> эх, тогда я никак не могу понять, почему программа повисает
> на одном из (все время на разных) WaitForSingleObject(MyMutex,
>  INFINITE);

Судя по всему проблема в попытке штатной синхронизации VCL нити из-за введения второго объекта синхронизации в виде мьютекса.


> Вова   (03.06.13 21:11) [11]
> объекты для работы с графикой являются потокобезопасными.

Забавно.


DVM   (2013-06-03 23:01:00) [14]

Что синхронизации все равно не отменяет.


Юрий Зотов   (2013-06-03 22:29:00) [15]

> Вова   (03.06.13 20:59) [10]

Если Вы откажетесь от битмапа из VCL и перейдете на битмап из WinAPI, то он будет замечательно работать в любых потоках.


Вова   (2013-06-03 21:11:00) [16]

объекты для работы с графикой являются потокобезопасными. Это такие классы, как TFont, TPen, TBrush, TBitmap, TDrawing и TIcon;

Graphics объекты потоко-безопасны. Вы не должны использовать главный VCL или CLX поток, чтобы обратиться к TFont, TPen, TBrush, TBitmap, TMetafile (VCL только), TDrawing (CLX только), или TIcon. Объекты Canvas могут использоваться вне Synchronize метода, необходимо только блокировать их перед применением и освобождать после,
для этого используются методы Lock() и Unlock()

Мож попробовать в отдельный неосновной поток скриншоты вытащить.


Вова   (2013-06-03 20:59:00) [17]

тогда смысл потоков несколько теряется, если каждый поток будет ждать пока основной поток сделает ему скриншот, кроме того что у основного и свои дела есть, то получится ерунда. А можно скриншоты делать во чтонибудь потокобезопасное? не в битмап?  
В сущности битмап я преобразую в массив позднее, забирая из него только нужное, а юзаю bmp просто потому что не знаю как иначе сделать скриншот...

После плясок с бубном, процесс пошел даже на INFINITE, но утечки памяти намекают, что битмап таки глючит, потому что так было и раньше (процедуры с битмапами отжирают память в потоках).


sniknik   (2013-06-03 09:48:00) [18]

> глобальный разделяемый ресурс
критическая секция, даже две. вход для изменений, т.е. параллельная работа с 2-мя и более битмапами в некоторых случаях невозможна, только последовательная.
а в случае "виснет" возможно из-за взаимолокирования, ждут друг друга...


Dimka Maslov   (2013-06-03 08:48:00) [19]

Убери все synchronize, которые не связаны с изменение свойств главной формы, либо, если это невозможно, замени их на SendMessage.


sniknik   (2013-06-03 08:12:00) [20]

> В этих функциях кстати есть создание объектов TBitmap
а битмап вроде имеет в модуле графикс (?) глобальный разделяемый ресурс который он локирует при работе. посмотреть нужно, по памяти смутно помню.

+
VCL не потокобезопасен, во всех справках написано и не устают повторять...  неважно есть там "лок" или нет, сказано "не потокобезопасен" значит не суйте его в поток... только через синхронизацию.


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо