本文介绍了多线程Delphi同步使用定时器和其他线程之间的关键部分的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是一个同步问题。我简化了我的问题,所以我有一个VCL计时器和几个线程。线程正在尝试以两个位图写入东西,而定时器正在尝试将图形绘制到图像(TImage)中。这是我的代码的修改,以便于更容易理解(这个粘贴代码非常模糊)。

It is a problem of synchronization. I made a simplification for my problem so I have a VCL Timer and a few threads. The threads are trying to write things in two bitmaps, and the timer is trying to draw the bitmaps into Images(TImage). Here is a modification of my code to be easier to understand(this paste code is very vague).

//------------------------------------------------------------------------------
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);

通常,线程在进入关键部分时会出现错误,或者几秒钟后,计时器将不会更长的时间吸引我任何东西。

Usually the threads gives me errors when entering in the critical section or after a few seconds the timer will no longer draw me anything.

推荐答案

尝试向您的代码添加异常处理,并且不要同时锁定这两个位图:

Try adding exception handling to your code, and don't lock both bitmaps at the same time:

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);

如果还是崩溃/错误,那么你没有显示的代码中有一个不同的错误。特别是考虑到你绝对不要错过进入/离开关键部分,除非关键部分本身已损坏。

If that is still crashing/erroring, then you have a different bug in code you have not shown. Especially considering that you should never get an error entering/leaving a critical section, unless the critical section itself is corrupted.

这篇关于多线程Delphi同步使用定时器和其他线程之间的关键部分的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-01 19:25