简体   繁体   English

Delphi Game Timer 程序在 1.5 到 2 小时后冻结,有时会出现异常“Canvas 不允许”

[英]Delphi Game Timer program freezes up after 1.5 to 2 hours and sometimes gives an exception "Canvas does not allow"

I have a simple program, single threaded, with a main form that has the controls, and another form with a bitmap and some TLabels on top of the bitmap that have the score, clock time, penalty time teams, and period.我有一个简单的程序,单线程,有一个有控件的主窗体,另一个窗体有 bitmap 和 bitmap 之上的一些 TLabels,有得分,时钟时间,罚时队和周期。

In my main form, I have a TTimer with a 500ms interval that, when started, computes the clock and any penalty times as it counts down and updates the labels on the other form.在我的主窗体中,我有一个间隔为 500 毫秒的 TTimer,它在启动时计算时钟和任何惩罚时间,因为它倒计时并更新另一个窗体上的标签。 The basic code in the timer event is:定时器事件中的基本代码是:

  // decrement main clock
  if ClockEndTime > Now then
    begin
      MainClockTime := ClockEndTime - Now;
...
  else
    // clock time is expired
    begin
      MainClockTime := ZeroTime;
      tmrMainClock.Enabled := False;
      ClockRunning := False;
...
    end;
    // update the timer values and overlay
    lblClock.Caption := FormatDateTime('n:ss',MainClockTime);
    fOverlay.lblClock.Caption := lblClock.Caption;
...

After 1 to 2 hours, the main from will stop responding, and I get a "Canvas does not allow" exception. 1 到 2 小时后,main from 将停止响应,并且出现“Canvas 不允许”异常。 The form with the labels and the bitmap has a blank spot where the time clock should be.带有标签和 bitmap 的表格在应该是时钟的地方有一个空白点。

异常错误

I have to close and restart the program for it to work again.我必须关闭并重新启动程序才能再次运行。 None of the controls on the main form will respond even after I acknowledge the exception.即使在我确认异常后,主窗体上的所有控件都不会响应。 It seems like the TTimer event might still be firing and having the same draw issues.似乎 TTimer 事件可能仍在触发并具有相同的绘制问题。 I have a hotkey for another function that still works while the program appears to be frozen.我有另一个 function 的热键,它在程序似乎被冻结时仍然有效。

I tried an exception handler in the timer event around where I update the label captions.我在更新 label 字幕的地方尝试了计时器事件中的异常处理程序。 It never shows my message box, but appears that it is going to the exception handler as I added code to close the other form, wait some time, and then reopen it.它从不显示我的消息框,但是当我添加代码以关闭另一个窗体时,它似乎会转到异常处理程序,等待一段时间,然后重新打开它。 The other form goes away and returns, but then nothing appears to draw on it.另一个形式消失并返回,但随后似乎没有任何东西可以画在它身上。 It shows what is in the background behind it.它显示了它背后的背景。

Do you think it is an issue because my main form code is updating labels on the other form?您认为这是一个问题,因为我的主表单代码正在更新另一个表单上的标签吗?

It is hard to test, as it involves waiting 1 to 2 hours for the issue to re-appear.很难测试,因为它需要等待 1 到 2 小时才能使问题重新出现。 I am wondering, has anyone experienced something like this?我想知道,有没有人经历过这样的事情?

I am using Delphi 10.4 Community Edition, and the program runs on Windows 11.我用的是Delphi 10.4社区版,程序运行在Windows 11。

One more interesting thing I noted the last time I tested is that, while my program was trying to update the labels, it also caused a GIF image on a completely unrelated Delphi 7 program that I have running to move positions.我上次测试时注意到的一件更有趣的事情是,当我的程序试图更新标签时,它还在我运行的一个完全不相关的 Delphi 7 程序上产生了一个 GIF 图像来移动位置。 I have no idea why one program would impact the other.我不知道为什么一个程序会影响另一个程序。 The only thing they have in common is the use of a TTimer.它们唯一的共同点是使用 TTimer。

The issue was a function I was using to get a pixel color from the screen.问题是我用来从屏幕获取像素颜色的 function。 I called this function in my TTimer event.我在我的 TTimer 事件中调用了这个 function。

function TfConfigureMute.GetPixelColor(X,Y: integer): TColor;
var
  dc: HDC;

begin
  // Get Device Context of windows desktop
  dc := GetDC(0);
  // Read the color of the pixel at the given coordinates
  Result := GetPixel(dc,X,Y);
  ReleaseDC(0,dc);
end;

I was originally missing the ReleaseDC(0,dc);我最初缺少ReleaseDC(0,dc); line.线。 So that was the leak.这就是泄漏。

Thanks for your time.谢谢你的时间。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM