Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2014.03.23;
Скачать: [xml.tar.bz2];

Вниз

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

 
Вова   (2013-06-02 21:23) [0]

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


 
Медвежонок Пятачок ©   (2013-06-02 22:49) [1]

естественно в том же из которого идет вызов


 
DVM ©   (2013-06-02 23:04) [2]


> Вопрос - что происходит, когда я вызываю их из TThread(т.
> е. в одной из процедур этого класса)?

Смотря из какого метода. И смотря как этот метод вызывался сам.
Чтобы некий код был выполнен в контексте потока, порожденного классом TThread надо, чтобы этот код вызван явно или косвенно из метода TThread.Execute и никак иначе.


 
Медвежонок Пятачок ©   (2013-06-02 23:16) [3]

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


 
Вова   (2013-06-03 01:12) [4]

эх, тогда я никак не могу понять, почему программа повисает на одном из (все время на разных) WaitForSingleObject(MyMutex, INFINITE); - если сделать ожидание не бесконечным, то ошибка "Invalid Handle". Причем виснут оба потока. Но TThread никогда не обращается в основной поток, если не считать за обращение вызов вот этих функций объявленных не в классе( они вызываются из процедур вызваных из Execute). В этих функциях кстати есть создание объектов TBitmap, и при этом в них используется bmp.Canvas.Lock/Unlock; а также получение скриншота, может в этот момент он лезет в основной поток? или я уже не знаю что копать, где искать.
Как временное решение это если INFINITE заменить на цифру, и сделать обработку ошибки, то в принципе работает, но как то это неправильно. Может есть идеи?


 
Вова   (2013-06-03 01:40) [5]

нет, и все таки нихрена не работат :-|


 
Германн ©   (2013-06-03 02:18) [6]


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

У тебя есть под руками код программы и отладчик. У нас под руками только отладчик. Что ты хочешь получить от нас? Когда наши программы "повисают", то мы ищем в них ошибку. Чаще всего с помощью отладчика.


 
sniknik ©   (2013-06-03 08:12) [7]

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

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


 
Dimka Maslov ©   (2013-06-03 08:48) [8]

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


 
sniknik ©   (2013-06-03 09:48) [9]

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


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

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

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


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

объекты для работы с графикой являются потокобезопасными. Это такие классы, как 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 22:29) [12]

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

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


 
DVM ©   (2013-06-03 23:01) [13]

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


 
Rouse_ ©   (2013-06-03 23:16) [14]


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

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


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

Забавно.


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


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); из за неверного параметра. стало быть другой поток постарался?


 
sniknik ©   (2013-06-04 09:48) [16]

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

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

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


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


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


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

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

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


 
Eraser ©   (2013-06-04 20:40) [18]


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

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


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


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; и вот это не могу перевести


 
Rouse_ ©   (2013-06-05 22:40) [20]

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


 
Rouse_ ©   (2013-06-05 22:42) [21]

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


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

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

На самом деле я изучаю предложение перейти на 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битмап в потоке.....


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



 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 сделаешь?


 
Rouse_ ©   (2013-06-05 23:44) [24]

Учится это хорошо, тем более оптимизации, но:
Пять 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-е крутится, поломаешь систему.


 
Rouse_ ©   (2013-06-05 23:51) [25]


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

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


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


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


о, спасибо.



Страницы: 1 вся ветка

Форум: "Начинающим";
Текущий архив: 2014.03.23;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.54 MB
Время: 0.003 c
3-1296733567
Михаил
2011-02-03 14:46
2014.03.23
Составление запроса MySQL


2-1370793552
Кристина
2013-06-09 19:59
2014.03.23
Помогите пожалуйста решить задачу! Никак не получается сделать(


15-1380924488
xayam
2013-10-05 02:08
2014.03.23
Помогите распознать мелодию


2-1370095621
Cobalt
2013-06-01 18:07
2014.03.23
TReader error: Invalid property value


2-1370709869
sanekgyrev
2013-06-08 20:44
2014.03.23
Написал,но вкралась ошибка( выделена восклицательным знаком)





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский