Форум: "Основная";
Текущий архив: 2003.04.21;
Скачать: [xml.tar.bz2];
Вниз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;
Скачать: [xml.tar.bz2];
Память: 0.5 MB
Время: 0.007 c