给大家看看一个奇怪的问题......

mme 2003-07-30 11:21:25
大家把下面这段copy运行一下,会发现很奇怪的资源不足....
拉一个TButton 和 TImage 就可以了.

//---------------------------------------------------------------------------
DWORD WINAPI mythread(LPVOID lpparam)
{
HDC hdc;
TMemoryStream *pms = new TMemoryStream();
Graphics::TBitmap *bmp = new Graphics::TBitmap();

bmp->PixelFormat = pf24bit;
bmp->Width = Screen->Width;
bmp->Height = Screen->Height;

for(;;)
{
Sleep(100);
hdc = GetDC(NULL); //复制屏幕
BitBlt(bmp->Canvas->Handle, r.Left, r.Top ,r.Right, r.Bottom,
hdc, 0, 0, SRCCOPY);
ReleaseDC(NULL,hdc);
pms->Position = 0;
bmp->SaveToStream(pms);
pms->Position = 0;
Form1->Image1->Picture->Bitmap->LoadFromStream(pms);
}
}
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Image1->Parent->DoubleBuffered = true;
DWORD dwthread;
::CreateThread(NULL,0,mythread,(LPVOID)"",0,&dwthread);
}


如果把bmp->PixelFormat = pf24bit;注释掉,又有很奇怪的结果:)
又如果加一句bmp->FreeImage();又可以长一点时间才出现资源不足.
唉,我的结论是TMemoryStream或者TBitmap很有问题D.
不知道各位有什么高论.
...全文
56 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
shh03 2003-08-02
  • 打赏
  • 举报
回复
int i;
for( i=0;i<10000000;++i)
{
try
{
// TQ->Acquire();
hdc = GetDC(NULL); //复制屏幕
BitBlt(bmp->Canvas->Handle, r.Left, r.Top ,r.Right, r.Bottom,
hdc, 0, 0, SRCCOPY);
ReleaseDC(NULL,hdc);
// TQ->Release();
pms->Position = 0;
bmp->SaveToStream(pms);
pms->Position = 0;
// TQ->Acquire();
Form1->Image1->Picture->Bitmap->LoadFromStream(pms);

// TQ->Release();
}
catch(...)
{
delete pms;
delete bmp;
break;
}
}
ShowMessage(IntToStr(i));

按下按钮后,如果鼠标一移动,出现异常,不移动鼠标经过一段时间后再移动,显示循环执行了200多次,(我可不能无限等它执行下去).我觉得问题出现两个线程对同一资源的访问上,当主线程中Image刷新时有可能另一个线程也在操作Image,应该互斥进行,另外,两个线程未同步,在关闭上有问题.
COKING 2003-08-02
  • 打赏
  • 举报
回复
主线程与你的线程在处理Form1->Image1时冲突吧!
因为当主线程在显示图片时,而你的线程刚好在Load图片!它该怎么办呢?
mme 2003-08-02
  • 打赏
  • 举报
回复
其实,原来我并没有用到Image1的,一样会有异常,我就用Image1来看看效果是怎么样的.

就发现显示的图片更是......
weibz0525 2003-08-01
  • 打赏
  • 举报
回复
是TMemoryStream的问题。
下面的写法就不会有问题,直接装载bmp,而不用流。
// bmp->PixelFormat = pf24bit;
bmp->Width = Screen->Width;
bmp->Height = Screen->Height;
for(;;)
{
Sleep(100);
Application->ProcessMessages();
hdc = GetDC(NULL); //复制屏幕
BitBlt(bmp->Canvas->Handle, r.Left, r.Top ,r.Right, r.Bottom,
hdc, 0, 0, SRCCOPY);
ReleaseDC(NULL,hdc);
pms->Position = 0;
bmp->SaveToStream(pms);
pms->Position = 0;
//Form1->Image1->Picture->Bitmap->LoadFromStream(pms);
Form1->Image1->Picture->Bitmap->Assign(bmp);

我认为如果bmp没有定义pixformat格式的化,内存流在从bmp接受数据的时候,就会改变数据的存储方式(就是几个象素对应几个字节),这样当bitmap从流中取数据的时候显示图象当然有麻烦。
反之如果pixformat定义了的话,流就应该按照格式存取数据了。
你可以把换几个参数,例如,pf16bit,pf8bit,虽然颜色不正确,但是他不会变化的乱七八糟。
mme 2003-08-01
  • 打赏
  • 举报
回复
听君一席话,胜读十年书 ^_^

谢谢楼上的参与.

明天就给分.

可惜很多人都不肯试试,我认为这一小段代码包涵了很多东西

线程 图象 流 还有异常,呵呵
jiangchun_xn 2003-08-01
  • 打赏
  • 举报
回复
我也晕。让他们同步吧。
不过我现在发现Stream真得很慢,鼠标都卡住了。
mme 2003-07-31
  • 打赏
  • 举报
回复
噢,突然发现我贴出来的程序漏了一句 ,在mythread 里面加一句

TRect r = Screen->DesktopRect;


mme 2003-07-31
  • 打赏
  • 举报
回复
还有就是 pf24bit 真是个大大的问题。我想破头也不明白。

为什么我设置了 pf24bit 出问题的机会就大大增加了。

如果设置为 pf4bit pf16bit 等情况,出现的问题也会不同。

我真的蒙了 ^_^
mme 2003-07-31
  • 打赏
  • 举报
回复
呵呵,楼上说得没错,就是new了一次而已。
其实呢, kingfish(八百里秦川@龙城异客),你说得不是很对,跟刷新是没有关系的。
不信你可以去掉Form1->Image1->Picture->Bitmap->LoadFromStream(pms);这一句。
结果会发现,仍然问题依旧 ^_^。 OutOfResources异常还会出现。


关键在于 bmp->SaveToStream(pms); 这一句上,如果你去掉这一句,无论你怎么改,
它都不会出现问题啦!
所以,我就判断TMemoryStream或者TBitmap 是有问题的。
kingfish 2003-07-31
  • 打赏
  • 举报
回复
比较->毕竟


我在考虑线程安全,
如果你设个断点, 让BCB IDE在最前面(FORM藏在后面),就不会有异常出来

VCL主线程去刷新,你的线程也在操作


pf24bit也是个问题

不懂, 关注
pp616 2003-07-31
  • 打赏
  • 举报
回复
for(;;)
{
Sleep(100);
hdc = GetDC(NULL); //复制屏幕
BitBlt(Form1->Image1->Canvas->Handle, r.Left, r.Top ,r.Right, r.Bottom,
hdc, 0, 0, SRCCOPY);
ReleaseDC(NULL,hdc);
}
jiangchun_xn 2003-07-31
  • 打赏
  • 举报
回复
我试了试,发现如果我的窗口不移动,不改变就没有异常抛出,只要最大化之类,就会发生异常,所以我估计HDC可能发生线程冲突,即使把SaveToSrtream去掉,关闭的时候也会发生异常。
mme 2003-07-31
  • 打赏
  • 举报
回复
to jiangchun_xn(一盒烟--姜春)

你说的没错,的确会产生"句柄无效"的异常,

可是有时候会产生"空间不足"的异常

还有其他的不知道什么异常.呼呼~~~~晕那.
mme 2003-07-31
  • 打赏
  • 举报
回复
如果不用线程,的确是不会出现问题.那么有谁可以解释一下,

不用 bmp->PixelFormat = pf24bit;

这一句出现的颜色变化问题呢? 注意,因为是死循环,只能够用ctrl+F2结束

void __fastcall TForm1::Button1Click(TObject *Sender)
{
Image1->Parent->DoubleBuffered = true;

HDC hdc;
TMemoryStream *pms = new TMemoryStream();
Graphics::TBitmap *bmp = new Graphics::TBitmap();
TRect r = Screen->DesktopRect;
//bmp->PixelFormat = pf24bit;
bmp->Width = Screen->Width;
bmp->Height = Screen->Height;

for(;;)
{
Sleep(100);
Application->ProcessMessages();
hdc = GetDC(NULL); //复制屏幕
//bmp->FreeImage();
BitBlt(bmp->Canvas->Handle, r.Left, r.Top ,r.Right, r.Bottom,
hdc, 0, 0, SRCCOPY);
ReleaseDC(NULL,hdc);
pms->Position = 0;
bmp->SaveToStream(pms);
pms->Position = 0;
Form1->Image1->Picture->Bitmap->LoadFromStream(pms);
}
}
pp616 2003-07-31
  • 打赏
  • 举报
回复
pms->clear;
weibz0525 2003-07-31
  • 打赏
  • 举报
回复
应该不是代码的问题,是线程在捣鬼。你可以把代码放到单独的函数里,而不是线程下,就可以执行。不会报异常的。
kingfish 2003-07-30
  • 打赏
  • 举报
回复
不delete也无所谓,比较就new了一次


主要是循环,会有OutOfResources异常
mme 2003-07-30
  • 打赏
  • 举报
回复
如果你看了程序就知道,有没有delete都没关系的.
因为我只是想试试一个死循环里面用bmp , pms 而已.
其实如果你运行就会知道,在for(;;)这个循环里面最多5 、6次就会抛出异常。。。
warton 2003-07-30
  • 打赏
  • 举报
回复
把pms ,bmp delete 了呀!

13,826

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder相关内容讨论区
社区管理员
  • 基础类社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧