我正在尝试在WinXP SP3上使用Borland的C ++ Builder 6编写一个多线程图形处理程序,但是遇到了(我认为)同步问题,并且无法找出原因。
主窗体(Form1)具有从文件加载的TPicture。线程通过Synchronize()调用获取此副本,并且工作正常。该线程在图像上做了一些工作,理论上,它定期更新主窗体图像。主表格还控制一台机器,并且是“第一度假村”紧急停止,因此阻止不是一种选择。一切都很好,直到主表单获取工作副本,或工作副本的副本(抱歉,但它已经到了),此时程序挂起,并且只响应来自IDE的“程序重置” 。一个糟糕的解决方案是将工作图像复制到剪贴板,然后从主窗体复制剪贴板到主窗体的图像。
//Synchronization routines:
//----------------------------------------------------------------
`void __fastcall ImageRout::update()
{
Form1->Image9->Picture->Bitmap->Assign(Imgcopy);
//never returns
}
//----------------------------------------------------------------
void __fastcall ImageRout::getimage()
{
Imgcopy->Assign(Form1->Image9->Picture);
}
//----------------------------------------------------------------
//do the initialisation things... Then,
//(data is a struct, loaded with image data via a Synchronize() call)
Imgcopy=new Graphics::TBitmap;
Imgcopy->Width=data.width;
Imgcopy->Height=data.height; //size the bitmap
while(Imgcopy->Canvas->LockCount!=1)
{
Imgcopy->Canvas->TryLock();
} //have to Lock() the image or it gets lost... Somewhere
Synchronize(getimage); //works fine
//do some work on Imgcopy
//"By the book"- attempt 1
//(rate (=15) is a 'brake' to stop every alteration being displayed)
update_count++;
if(update_count>rate) //after a few iterations, update
{ //user interface
Synchronize(update); //fails: never returns from Synchronize call
update_count=0;
}
经过多次尝试失败后,我想出了这个。
//in the thread...
update_count++;
if(update_count>rate)
{
EnterCriticalSection(&Form1->mylock1);
Form1->tempimage->Assign(Imgcopy); //tempimage is another bitmap,
InterlockedExchange(&Form1->imageready,1);//declared in the main Form
LeaveCriticalSection(&Form1->mylock1); //and is only ever accessed
update_count=0; //inside a critical section
}
//...and in the main Form....
if(imageready==1)
{
EnterCriticalSection(&mylock1);
Image9->Picture->Bitmap->Assign(tempimage); //Fails here
InterlockedExchange(&gotimage,1);
InterlockedExchange(&imageready,0);
LeaveCriticalSection(&mylock1);
}
所以,绝望。
//in the thread...
update_count++;
if(update_count>rate)
{
Synchronize(update);
EnterCriticalSection(&Form1->mylock1);
Form1->tempimage->Assign(Imgcopy);
Clipboard()->Assign(Imgcopy);
InterlockedExchange(&Form1->imageready,1);
LeaveCriticalSection(&Form1->mylock1); */
update_count=0;
}
//and in the main Form...
if(imageready==1)
{
EnterCriticalSection(&mylock1);
if (Clipboard()->HasFormat(CF_BITMAP))
{
Image9->Picture->Bitmap->Assign(Clipboard());
}
InterlockedExchange(&gotimage,1);
InterlockedExchange(&imageready,0);
LeaveCriticalSection(&mylock1);
}
这最后的尝试虽然相对缓慢,但由于剪贴板的开销,并且它充其量只是一个糟糕的拐杖。我怀疑剪贴板正在强制执行其他失败的同步工作,但正如我之前所说,我无法理解为什么。可能是什么问题?
答案 0 :(得分:0)
感谢您的评论,雷米。当我试图解决问题时,他们让我摆脱了“眩晕”的困扰。我忘记了Windows需要移动内存块,如果锁定它们就无法执行此操作。
同步(更新)调用(上面的代码块1)的初始问题是由于我在调用期间仍然锁定(从线程内部)工作副本(Imgcopy),导致主窗体随后无法访问它。我怀疑(但尚未调查 - 代码已经消失了)相同的根本原因是在代码块2中工作。
在访问之前锁定每个位图,然后立即解锁就解决了这个问题。
Peter O,感谢您的编辑 - 我没有意识到我的初始帖子中有太多的开销。