Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 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
1-67263
neodiX
2003-04-07 22:49
2003.04.21
Thread, Synchronize, BitBlt - в итоге белый битмап!


1-67363
evvcom
2003-04-09 02:07
2003.04.21
Проблемы с debuginfo в dll


1-67297
Карелин Артем
2003-04-11 07:36
2003.04.21
Оптимальное хранение StringList в памяти.


1-67250
Val
2003-04-10 15:54
2003.04.21
Не закрывается Excel. Почему?


1-67265
Demon[DZ]
2003-04-11 13:00
2003.04.21
Cursor





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский