多线程同步

时间:2016-02-29 19:32:16

标签: c++ multithreading graphics c++builder

我正在尝试在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);
}

这最后的尝试虽然相对缓慢,但由于剪贴板的开销,并且它充其量只是一个糟糕的拐杖。我怀疑剪贴板正在强制执行其他失败的同步工作,但正如我之前所说,我无法理解为什么。可能是什么问题?

1 个答案:

答案 0 :(得分:0)

感谢您的评论,雷米。当我试图解决问题时,他们让我摆脱了“眩晕”的困扰。我忘记了Windows需要移动内存块,如果锁定它们就无法执行此操作。

同步(更新)调用(上面的代码块1)的初始问题是由于我在调用期间仍然锁定(从线程内部)工作副本(Imgcopy),导致主窗体随后无法访问它。我怀疑(但尚未调查 - 代码已经消失了)相同的根本原因是在代码块2中工作。

在访问之前锁定每个位图,然后立即解锁就解决了这个问题。

Peter O,感谢您的编辑 - 我没有意识到我的初始帖子中有太多的开销。