这是同步问题。我为我的问题做了简化,所以我有一个VCL计时器和几个线程。线程试图用两个位图写东西,而计时器正试图将位图绘制成图像(TImage)。以下是对我的代码的修改,以便更容易理解(此粘贴代码非常模糊)。
//------------------------------------------------------------------------------
Procedure TMyForm.Add(iX,iY,iNr:integer);
begin
EnterCriticalSection(csCriticalSection);
bmRed.Canvas.Lock;
bmBlue.Canvas.Lock;
//.... drawing etc...
bmRed.Canvas.TextOut(iX,iY,IntToStr(iNr));
bmBlue.Canvas.TextOut(iX,iY,IntToSTr(iNr));
bmRed.Canvas.Unlock;
bmBlue.Canvas.Unlock;
LeaveCriticalSection(csCriticalSection);
end;
//------------------------------------------------------------------------------
procedure TMyForm.tmTimer(...);
begin
EnterCriticalSection(csCriticalSection);
bmRed.Canvas.Lock;
bmBlue.Canvas.Lock;
//Drawing on bmRed and bmBlue
imBlue.Canvas.Draw(bmBlue);
imRed.Canvas.Draw(bmBlue);
bmRed.Canvas.Unlock;
bmBlue.Canvas.Unlock;
LeaveCriticalSection(csCriticalSection);
end;
//------------------------------------------------------------------------------
Procedure TMyThread.Execute();
begin
Randomize;
while not terminated do
begin
MyFormInstance.Add(Random(100),Random(100),Random(100));
Sleep(20);
end;
end;
initialization
InitializeCriticalSection(csCriticalSection);
finalization
DeleteCriticalSection(csCriticalSection);
通常线程在进入临界区时会给我错误,或者在几秒钟之后计时器将不再为我画任何东西。
答案 0 :(得分:10)
尝试在代码中添加异常处理,并且不要同时锁定两个位图:
var
csCriticalSection: TRTLCriticalSection;
procedure TMyForm.Add(iX,iY,iNr:integer);
begin
EnterCriticalSection(csCriticalSection);
try
bmRed.Canvas.Lock;
try
bmRed.Canvas.TextOut(iX,iY,IntToStr(iNr));
finally
bmRed.Canvas.Unlock;
end;
bmBlue.Canvas.Lock;
try
bmBlue.Canvas.TextOut(iX,iY,IntToSTr(iNr));
finally
bmBlue.Canvas.Unlock;
end;
finally
LeaveCriticalSection(csCriticalSection);
end;
end;
procedure TMyForm.tmTimer(Sender: TObject);
begin
EnterCriticalSection(csCriticalSection);
try
bmRed.Canvas.Lock;
try
imRed.Canvas.Draw(bmBlue);
finally
bmRed.Canvas.Unlock;
end;
bmBlue.Canvas.Lock;
try
imBlue.Canvas.Draw(bmBlue);
finally
bmBlue.Canvas.Unlock;
end;
finally
LeaveCriticalSection(csCriticalSection);
end;
end;
procedure TMyThread.Execute;
begin
Randomize;
while not Terminated do
begin
MyFormInstance.Add(Random(100),Random(100),Random(100));
Sleep(20);
end;
end;
initialization
InitializeCriticalSection(csCriticalSection);
finalization
DeleteCriticalSection(csCriticalSection);
如果仍然崩溃/错误,那么您在未显示的代码中有一个不同的错误。特别是考虑到进入/离开关键部分时不应该出错,除非关键部分本身已损坏。