Форум: "Начинающим";
Текущий архив: 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);
Это еще один в Button8ClickSelectObject(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