Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2003.04.21;
Скачать: CL | DM;

Вниз

Thread, Synchronize, BitBlt - в итоге белый битмап!   Найти похожие ветки 

 
neodiX ©   (2003-04-07 22:49) [0]

Есть сервис, в нем форма, в модуле формы вызывается поток в котором делаются снимки экрана. При старте сервиса, форма прячется и стартуется поток в котором копируется экран (пока я не остановлю поток),а в трее появляется иконка. Так вот, при наведении курсора на иконку в трее или при любом обращении к форме, битмап, скопированмый функ. bitblt, становится в прямом смысле белым. Копирование битмапа происходит синхронно (т.е. synchronize(copybmp)). Я не могу понять, КАК какое то сообщение к иконке или форме может повлиять на работу потока, а именно на результат функ. bitblt, которая выполнятся в synchronize!
Интересно то, что идентичный код, когда програма не сервис типа, работает прекрасно, и с формой можно работать и экран копировать.
Может кто обяснит это аномальное явление?


 
Игорь Шевченко ©   (2003-04-08 14:44) [1]

Слишком мало информации для диагностики, IMHO


 
neodiX ©   (2003-04-08 15:03) [2]

2 Игорь Шевченко
Вот код. Код оптимизирован, но самая суть осталась. В сервисе создается форма, а после нажатия кнопки на форме, запускается этот(ниже) поток.
bmp - обявлен как глобальный параметр в модуле (т.е. не поле в Tsendcopythread, а просто в модуле)
Функция копирует битмап
procedure Tsendcopythread.copyframe;
var DCtemp:HDC;
begin
DCtemp:=getDC(0);
bitblt(bmp.Canvas.Handle,0,0,1024,768,DCtemp,0,0,SRCCOPY);
releaseDC(0,DCtemp);
end;


эта фунция вырезает из bmp кусочек поменьше (просто так надо) и посылает в сеть:
procedure TSendcopythread.copyframe_s;
var bmpt:tbitmap;
s:string;
begin
try
bmpt:=TBitmap.Create;
bmpt.Width:=partW;
bmpt.Height:=gy;
bitblt(bmpt.Canvas.Handle,0,0,100,100,bmp.Canvas.Handle,0,0,SRCCOPY);
s:=convertbmptostr(bmpt);
client.ScreenClient.Socket.SendText(s);
finally
bmpt.Free
end;
end;

главный метод потока, в котором вызываются, вышеопсианные процедуры:
procedure TSendCopyThread.Execute;
begin
FreeOnTerminate:=true;
while (not terminated and client.ScreenClient.Active) do begin
synchronize(copyframe);
bmp.pixelformat:=pf8bit;
synchronize(copyframe_s);
sleep(1);
end;
end;


 
neodiX ©   (2003-04-08 15:06) [3]

sorry, забыл!
в данном случае partW и gy в copyframe_s равны - 100


 
neodiX ©   (2003-04-08 15:08) [4]

добавление :
bmp создается перед циклом в методе ехеcute
bmp:=TBitmap.Create;
bmp.Width:=screen.width
bmp.Height:=screen.height;

освобождается после цикла


 
neodiX ©   (2003-04-08 15:37) [5]

ради интереса в методе copyframe_s вместо client.ScreenClient.Socket.SendText(s); написал:

form2.Canvas.Lock;
form2.Canvas.Draw(0,0,bmpt);
form2.Canvas.UnLock;

теперь явно видно, что перед посылкой кадра, бмп белый. Можете попробывать.
Выяснил, что это происходит именно тогда, когда происходит обращение к форме (или мышь на ней двинулась или форма двинулась), но не тогда когда происходит рисование на форме.
Ну как же это исправить?


 
Fiend ©   (2003-04-08 15:40) [6]

Думаю это очень просто исправить, вам надо заблокировать канву картинки ну или формы на которой она лежит.
Лучше конечно канву картинки. Тока не забудьте потом разблокировать


 
Digitman ©   (2003-04-08 15:40) [7]

непонятно, для чего все это в доп.трэде реализовано


 
Fiend ©   (2003-04-08 15:44) [8]

То Digitman:
оно конечно действительно непонятно, но всё же доступ к рисунку из двух потоков одновременно - есть очень нехорошо.


 
neodiX ©   (2003-04-08 15:49) [9]

2 Fiend
ты имеешь ввиду что то такое:
bmpt:=TBitmap.Create;
bmpt.Width:=partW;
bmpt.Height:=gy;
bmpt.canvas.lock;
bitblt(bmpt.Canvas.Handle,0,0,100,100,bmp.Canvas.Handle,0,0,SRCCOPY);
s:=convertbmptostr(bmpt);
client.ScreenClient.Socket.SendText(s);
bmpt.canvas.Unlock;
finally
bmpt.Free

или ты говоришь про bmp? тогда где ее блокировать в каком именно месте?

2 Digitman

> непонятно, для чего все это в доп.трэде реализовано

дело в том, что в сервисе это не одна функция, и параллельно может выполнятся еще несколько функций. Да и вообще после многих опытов (даже не спрашивай каких :)) выяснил что без потока в моем случае никак


 
neodiX ©   (2003-04-08 15:51) [10]

2 Fiend
дело в том, что в моем случае, второй поток вызыватся никогда не будет. Т.е. в одно время будет выполнятся только один поток.


 
Fiend ©   (2003-04-08 15:51) [11]

Вновь созданный блокировать не надо. надо тот который получает события от окна, т.е. тот который лежит на форме(bmp)


 
neodiX ©   (2003-04-08 15:56) [12]

2 Fiend
Понимаешь на форме вообше ничего не лежит. Все копируется с десктопа (getdc(0)) в дин. битмап . Притом выше, в коде я уже так попробывал, все равно тоже.


 
neodiX ©   (2003-04-08 16:01) [13]

Если у кого есть время вот исходники сервиса, котрый я только что насписал, что бы показать проблему. (ехе так как selfextract): http://193.219.57.84/haja_serv.exe


 
Digitman ©   (2003-04-08 16:03) [14]

судя по приведенному телу метола Execute ничего сколь-либо "тяжелого" по вычислениям доп.поток не делает

та же самая CopyFrame() с тем же успехом (и меньшими затратами) может вызываться и быть выполнена непосредственно в осн.потоке



 
neodiX ©   (2003-04-08 16:15) [15]

в данном случае ИМХО не в этом проблема. Надо выяснить кто вмешивается в процедуру копирования экрана.


 
neodiX ©   (2003-04-08 16:30) [16]

ради интереса вместо вывода скопированного битмапа на форму в методе copyframe_s, сделал что бы он сохранялся на хард (что by не было обращения к канве формы из потока) и что вы думаете ? ..... то же самое.


 
Digitman ©   (2003-04-08 16:32) [17]

пока из всего этого я вижу явную несуразицу

с одной стороны :


> bmp - обявлен как глобальный параметр в модуле


с другой :

procedure TSendCopyThread.Execute;
begin
..
bmp.pixelformat:=pf8bit; // обращение к non-thread-safe ресурсу !!
..
end;


 
neodiX ©   (2003-04-08 16:43) [18]

вот, переписал метод copyframe_s и Execute:
procedure My.copyframe_s;
var bmpt:tbitmap;
s:string;
begin
try
bmpt:=TBitmap.Create;
bmpt.Width:=100;
bmpt.Height:=100;
bitblt(bmpt.Canvas.Handle,0,0,100,100,bmp.Canvas.Handle,0,0,SRCCOPY);
bmp.pixelformat:=pf8bit; // появился здесь
bmpt.SaveToFile("c:\"+inttostr(random(10000))+".bmp");
{ form2.Canvas.Lock;
form2.Canvas.Draw(0,0,bmpt);
form2.Canvas.UnLock; }
finally
bmpt.Free
end;
end;



procedure MY.Execute;
var DCtemp:HDC;
begin
FreeOnTerminate:=true;
bmp:=TBitmap.Create;
bmp.Width:=screen.width div 2;
bmp.Height:=screen.height div 2;
while (not terminated ) do begin
//synchronize(copyframe);
DCtemp:=getDC(0);
bitblt(bmp.Canvas.Handle,0,0,512,359,DCtemp,0,0,SRCCOPY);
releaseDC(0,DCtemp);
// bmp.pixelformat:=pf8bit; нет, теперь в copyframe_s
synchronize(copyframe_s);
sleep(100);
end;
bmp.Free;
end;


странно, все равно в итоге bmp"шки на харде белые



 
neodiX ©   (2003-04-08 16:54) [19]

2 Digitman
Ну ты даешь, прямо в точку! То, что я передвинул bmp.pixelformat:=pf8bit; в synchronize - не помогло, а вот как убрал эту строку, так все стало ОК. Но т.к. мне все равно надо юзать pixelformat, то теперь вопрос где это надо делать, если не в synchronize и методе ехеcute?


 
neodiX ©   (2003-04-08 17:27) [20]

В любом случае, всем участникам данного топика, очень благодарен за истраченные кванты времени на решение моей проблемы. Спасибо.

P.S. файл с примером ( http://193.219.57.84/haja_serv.exe) с сервера стер.


 
Digitman ©   (2003-04-08 17:36) [21]


> neodiX


ну так - правильно ! изменяя формат ПОСЛЕ операции бит-блиттинга ты фактически инициализируешь битмап "с нуля" ! не взирая на его прежнее содержимое)

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


 
neodiX ©   (2003-04-08 17:40) [22]

ok, попробую


 
neodiX ©   (2003-04-09 01:02) [23]

Все получилось! Еще раз всем спасибо.



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

Текущий архив: 2003.04.21;
Скачать: CL | DM;

Наверх




Память: 0.53 MB
Время: 0.023 c
8-67400
Bananos
2003-01-20 00:00
2003.04.21
Bitmap.ScanLine


1-67277
Алексей Глеб
2003-04-11 11:10
2003.04.21
DLL & TFrame


7-67597
GRS
2003-02-19 20:58
2003.04.21
Кнопка ПУСК смена tooltip


14-67521
mazepa
2003-04-02 16:53
2003.04.21
dcu


14-67446
X-Man
2003-04-05 15:04
2003.04.21
HTML Print???