多线程同步



我正在尝试使用 WinXP SP3 上的 Borland 的 C++ Builder 6 编写多线程图形处理程序,但遇到了(我认为)同步问题,并且无法弄清楚原因。

主窗体 (Form1) 具有从文件加载的 TPicture。线程通过 Sync() 调用获取此副本,并且工作正常。线程对图像执行一些工作,理论上,它会定期更新主窗体图像。主表单还控制机器,并且是"第一手段"紧急停止,因此无法选择阻塞。一切都很好,直到主窗体获得工作副本或工作副本的副本(对不起,但它必须这样做),此时程序挂起,并且仅响应来自 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);
}

最后一次尝试有效,尽管相对较慢,因为剪贴板开销,它充其量是一个糟糕的拐杖。我怀疑剪贴板正在强制执行否则失败的同步工作,但是,正如我之前所说,我无法理解为什么。可能是什么问题?

谢谢你的评论,雷米。他们把我从试图解决问题时陷入的"晕眩"中惊醒。我忘记了Windows需要移动内存块,如果锁定它们,则无法执行此操作。

同步(更新)调用

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

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

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

相关内容

  • 没有找到相关文章