- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试为我的学校项目制作街机游戏。基本思想是在主线程之外的其他线程中进行所有数学运算和绘图,并且仅将主线程用于输入例程。绘图是由保存在外部单元中的程序完成的,它是通过创建位图,然后在位图上绘制部分环境,最后在主窗体的 Canvas 上绘制位图来完成的。当我完成绘图程序时,我尝试从主线程运行它,并设法使 everythink 按预期工作(除了整个应用程序窗口被卡住的事实,但由于主线程一直在不停地工作,所以就像这是预料之中的)。然后我尝试将该过程放在其他线程中,它停止工作(尽管调试例程报告该过程被重复执行,但它没有绘制任何东西)。在添加和删除调试例程后,它开始无缘无故地工作,但并不可靠。在大约 80% 的情况下,它运行顺利,但在其余情况下,它会在 10 到 30 帧后停止,有时甚至不会在最后一帧驱动某些环境部分而卡住。
主表单单元的重要部分如下所示
procedure TForm1.Button1Click(Sender: TObject);
begin
running:=not running;
if running then AppTheard.Create(false);
end;
Procedure AppTheard.execute;
begin
form1.Button1.Caption:='running';
while running do begin view.nextframe; end;
form1.Button1.Caption:='no longer running';
end;
而另一个单元中的下一帧过程如下所示
Camera = class
owner:Tform;
focus:GravityAffected;
Walls:PBlankLevel;
Creeps:MonsterList;
FrameRateCap,lastframe:integer;
Background:TBitmap;
plocha:TBitmap;
RelativePosY,RelativePosX:integer;
constructor create(owner:Tform; focus:GravityAffected; Walls:PBlankLevel; Creeps:MonsterList; FrameRateCap:integer; background:TBitmap);
procedure nextframe;
end;
procedure camera.nextframe;
var i,i1,top,topinfield, left,leftinfield: integer ;
procedure Repair
//some unimportant math here
Procedure vykresli(co:vec);
begin
if co is gravityaffected then
plocha.Canvas.Draw(co.PositionX*fieldsize+Gravityaffected(co).PosInFieldX-Left*fieldsize+leftinfield-co.getImgPosX,
co.PositionY*fieldsize+Gravityaffected(co).PosInFieldY-top*fieldsize+topinfield-co.getImgPosY,
co.image)
else
plocha.Canvas.Draw(co.PositionX*fieldsize-Left*fieldsize+leftinfield-co.getImgPosX,
co.PositionY*fieldsize-top*fieldsize+topinfield-co.getImgPosY,
co.image);
end;
begin
// some more unimportant math
vykresli(focus);
For i:= Left+1 to left+2+(plocha.Width div fieldsize) do //vykreslení zdí
For i1:= Top+1 to top+2+(plocha.Height div fieldsize) do
if (i< Walls.LevelSizeX) and (i1< Walls.LevelSizeY) and (i>=0) and (i1>=0) and walls.IsZed(i,i1) then
begin vykresli(walls^.GiveZed(i,i1)^);end;
while abs((gettickcount() mod high(word))-lastframe) < (1000 div FrameRateCap) do sleep(1);
lastframe:=gettickcount mod high (word);
owner.Canvas.Draw(-fieldsize,-fieldsize,plocha);
end;
有人可以告诉我我做错了什么吗?
编辑:我得到了我要求的帮助,但又过了几年,我意识到我真正需要的建议是根本不使用线程并尝试像 this 这样的东西。相反。
最佳答案
我发现您在这方面的方法有很多问题。
1) 所有 VCL 交互都必须在主线程中完成
您的线程正在直接访问 VCL 控件。你不能这样做,因为 VCL 不是线程安全的。您必须将所有事件同步回主线程,并让主线程完成这项工作。
2) 所有自定义 UI 绘图(到表单)必须在表单的 OnPaint
事件中完成。
这解释了为什么它有时有效而其他时候无效。窗体是自动绘制的,如果您不使用此事件,您的自定义绘图将仅由 VCL 绘制。
3) 所有 UI 绘制必须在主线程中完成
这让我们回到第 1 点和第 2 点。VCL 不是线程安全的。你的辅助线程应该只负责执行计算,而不是绘制 UI。在执行一些计算或做一些冗长的工作后,您必须将结果同步回主线程,让主线程进行绘图。
4)线程应该是完全独立的
你不应该在这个辅助线程中放置任何知道它将如何显示的代码。在您的情况下,您明确引用了表单。您的线程甚至不知道它是否被表单使用。您的线程应该只执行冗长的计算工作,并且对用户界面的考虑绝对为 0。当您需要指示它重绘时,将事件同步回您的主窗体。
结论
你需要研究线程安全。通过这样做,您将能够回答您自己的大部分问题。使这个线程严格只用于处理繁重的工作,否则会使 UI 陷入困境。不要太担心用户界面慢,大多数现代计算机都能在几分之一秒内完成复杂的绘图。这不需要在单独的线程中。
编辑
经过几年的经验,我开始意识到上面的#3 不一定是正确的。事实上,在许多情况下,在线程内执行详细绘图是一种很好的方法,但主线程将只负责向用户呈现该图像。
当然,这本身就是一个完整的话题。您需要能够安全地将在一个线程中管理的图像绘制到另一个线程。这也需要使用 Synchronize
。
关于multithreading - 从非主线程绘制到主窗体 Canvas ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26725563/
在 Windows 世界中,什么是正确的名称。具有导出函数的老式 C++ DLL?不是 COM DLL,也不是 .NET DLL。我们以前通过调用 LoadLibrary() 和 GetProcAdd
目前我正在使用javaEE7,我有一个场景如下。在我的 JSF Web 应用程序中,我有一个事件监听器(不是 JSF 事件),当事件调用时,它会执行某些操作,然后将这些信息更新到我的 Web 应用程序
这不是 AJAX 请求/响应回调问题... 我正在使用 Dojo 1.5 构建网格。我正在尝试 dojo.connect具有功能的扩展/收缩按钮。我的问题是 grid.startup()在创建实际 D
非 Webkit Opera 是 very specific在某些功能中,因此通常通过 JavaScript 检测到 the following way . 但是,Opera Next 几乎是 Goo
我已查看以下链接中给出的所有日志,但未能找到 IP 地址: https://developer.couchbase.com/documentation/server/3.x/admin/Misc/Tr
我有一个命令行程序,它根据一组源文件生成一个我想在我的 Android gradle 构建 (A) 中使用的 jar 文件。这个命令行程序只是将一个 jar 文件存储在磁盘上的一个目录中。 我如何创建
下面的 htaccess 命令将所有非 www 转移到 http www RewriteEngine On RewriteCond %{HTTP_HOST} !^www\. RewriteRule ^
我正在使用自定义链接器脚本将内核镜像分为两部分。第一个是普通代码和数据,第二个是初始化代码和不再需要时将被丢弃的数据。初始化部分也不像内核本身那样在地址空间之间共享,因此如果 fork() 仍然存在(
这个问题在这里已经有了答案: Several unary operators in C and C++ (3 个答案) What is the "-->" operator in C++? (29
假设我有一个类设置如下: class A { public: virtual void foo() { printf("default implementation\n"); } }; c
#include using namespace std; int main(int argc, char *argv[]) { int i=-5; while(~(i)) {
近期,百度搜索引擎变化无常,很多企业站、行业站、门户站、论坛等站点遭到了降权,特别是比比贴分类信息网直接遭到了拔毛,这对于广大站长来说是一种打击,也是各个企业、行业的打击。 至今,很多网站已经恢复
我现在正在使用 IBM TPM v1332 + IBM TSS v1470 并尝试将一些基本关键字/密码存储到 TPM 上的非 volatile 内存中。我找到了两种方法。一种是创建一个密封对象并使用
我的 PHP 脚本中有一个正则表达式,如下所示: /(\b$term|$term\b)(?!([^)/iu 这与 $term 中包含的单词匹配,只要前后有单词边界并且它不在 HTML 标记内即可。 但
我想显示用户名称地址(请参阅 www.ipchicken.com ),但我唯一能找到的是 IP 地址。我尝试了反向查找,但也没有用: IPAddress ip = IPAddress.Parse(th
只有 UI 线程能够显示到屏幕上,还是其他线程也可以这样做? 最佳答案 不,您只能直接从 UI 线程访问 UI,但您可以编码来自其他线程的结果,例如使用 Control.Invoke 或 contro
我正在使用现代 Excel 滚动条(不是旧的 ActiveX 类型,即开发人员 > 插入 > 表单控件 > 滚动条)并且想检测它的值何时更改。我找不到有关此类对象的更改事件的任何信息。您可以在单击时分
当我使用这段代码时 IE 6 确实正确使用了指定的样式表,但所有其他浏览器在应该使用基本上声明的样式表时会忽略这两种样式表,如果您不是 IE,请使用此样式表。 有什么想法吗? 最佳答案 n
我想指定 2 mssql 表之间的关系。 付款类别和付款。 paymentcategory.id 加入 payout.category 列。 在 payout.json 模型中 我指定为外键:id,
我正在尝试制作非 volatile UDF,但似乎不可能。因此,这是我非常简单的test-UDF: Option Explicit Dim i As Integer Sub Main() i = 0
我是一名优秀的程序员,十分优秀!