求助:这段多线程代码为什么不稳定?

hpygzhx520 2013-07-03 03:41:22
先描述一下情况:

程序用一按钮启动定时器(触发间隔5秒),定时器内循环创建8个线程,传递多个参数。线程函数就是在内存里面创建一个位图,然后写字。程序运行几分钟,或十几分钟后就会崩溃,无法定位出错点。

线程内的代码都是局部变量,也没有操作窗口上面的控件,我就不明白为什么不稳定?

初学delphi不久,折腾了一个星期无果,来此求助。不胜感激。

全部代码就这么点:

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, StdCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
Timer1: TTimer;
Image1: TImage;
Button2: TButton;
Image2: TImage;
Button3: TButton;
procedure Button1Click(Sender: TObject);
procedure Timer1Timer(Sender: TObject);

private
{ Private declarations }
public
{ Public declarations }
end;

PParData = ^TParData;

TParData = record
cardNum:Integer;
stationName:string;
trunkNo:string;
relatedFormID:string;
materialName:string;
taskState:string;
materialNum:Integer;
sl1:integer;
end;
var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
Timer1.Enabled:=True;//启动定时器
end;


function LEDThread(AParData: PParData):Boolean; stdcall;
var
txtRect: Trect;
fontObj: Longint;
hBrush: Longint;
memDC: Longint;
hDisplayDC: Longint;
newBitmap: Longint;
oldpBitmap: Longint;
myFont: Longint;
oneItem:string;
begin
hDisplayDC := GetDC(0);
memDC := CreateCompatibleDC(hDisplayDC);
newBitmap := CreateCompatibleBitmap(hDisplayDC, 320, 96);
oldpBitmap := SelectObject(memDC, newBitmap);
SetBkMode(memDC, TRANSPARENT);
hBrush := CreateSolidBrush(0);
FillRect(memDC, txtRect, hBrush);
DeleteObject(hBrush);
SetTextColor(memDC, 255);
myFont := CreateFont(14, 7, 0, 0, 0, 0, 0, 0, GB2312_CHARSET,
OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, PROOF_QUALITY, FF_ROMAN, '宋体');
fontObj := SelectObject(memDC, myFont);
DeleteObject(fontObj);

with txtRect do // 出口
begin
Left := 130;
Top := 16 * 0;
Right := 320;
Bottom := 16 * 1;
end;
oneItem:=AParData.stationName;
//尝试用TextOut和DrawText两个函数,效果都差不多
TextOut(memDC,txtRect.Left, txtRect.Top ,PChar(oneItem),Length(oneItem));
//DrawText(memDC, PChar(AParData.stationName), -1, txtRect,DT_SINGLELINE Or DT_CENTER Or DT_VCENTER);
//如果函数代码到此结束,观察,测试,程序是稳定的。一旦DrawText或TextOut在函数内使用大于一次,就会很不稳定
with txtRect do
begin
Left := 8;
Top := 16 * 1;
Right := 320;
Bottom := 16 * 2;
end;
oneItem:='车牌号: ' + AParData.trunkNo;
TextOut(memDC,txtRect.Left, txtRect.Top ,PChar(oneItem),Length(oneItem));
//DrawText(memDC, PChar('车牌号: ' + AParData.trunkNo), -1, txtRect,DT_SINGLELINE Or DT_LEFT Or DT_VCENTER);

with txtRect do
begin
Left := 8;
Top := 16 * 2;
Right := 320;
Bottom := 16 * 3;
end;
oneItem:='品牌: ' +AParData.materialName;
TextOut(memDC,txtRect.Left, txtRect.Top ,PChar(oneItem),Length(oneItem));
//DrawText(memDC, PChar('品牌: ' + AParData.materialName), -1, txtRect,DT_SINGLELINE Or DT_LEFT Or DT_VCENTER);

with txtRect do
begin
Left := 8;
Top := 16 * 3;
Right := 320;
Bottom := 16 * 4;
end;
oneItem:='计划出库: ' + inttostr(AParData.materialNum)+ ' 件,' + ' 已出库:' + inttostr(AParData.sl1) + ' 件';
TextOut(memDC,txtRect.Left, txtRect.Top ,PChar(oneItem),Length(oneItem));
//DrawText(memDC, PChar('计划出库: ' + inttostr(AParData.materialNum)+ ' 件,' + ' 已出库:' + inttostr(oneParData.sl1) + ' 件'), -1, txtRect,DT_SINGLELINE Or DT_LEFT Or DT_VCENTER);

with txtRect do
begin
Left := 8;
Top := 16 * 4;
Right := 320;
Bottom := 16 * 5;
end;
oneItem:='单据: ' + AParData.relatedFormID;
TextOut(memDC,txtRect.Left, txtRect.Top ,PChar(oneItem),Length(oneItem));
//DrawText(memDC, PChar('单据: ' + AParData.relatedFormID), -1, txtRect,DT_SINGLELINE Or DT_LEFT Or DT_VCENTER);
DeleteDC(memDC);
ReleaseDC(0, hDisplayDC);
DeleteObject(newBitmap);
DeleteObject(oldpBitmap);
Sleep(1000); //暂停,方便从任务管理器观察线程
Result:=True;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
var i:Integer;
hThread: THandle;
ThreadID: DWord;
vParData: PParData;
begin
Timer1.Enabled:=false;
for i := 0 to 7 do //创建8个线程
begin
ThreadID:=0;
New(vParData);
vParData.cardNum:=1;
vParData.stationName:='a';
vParData.trunkNo:='b';
vParData.relatedFormID:='c';
vParData.materialName:='d';
vParData.taskState:='e';
vParData.materialNum:=2;
vParData.sl1:=3;
hThread := CreateThread(nil, 0, @LEDThread, vParData, 0, ThreadID);
end;
Timer1.Enabled:=True;
end;

end.


...全文
365 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
hpygzhx520 2013-07-03
  • 打赏
  • 举报
回复
感谢各位,明天测试!非常感谢。
cankoo 2013-07-03
  • 打赏
  • 举报
回复
sololie 好热心哦
sololie 2013-07-03
  • 打赏
  • 举报
回复
创建线程用BeginThread,参数返回值跟CreateThread一样 hThread := BeginThread(nil, 0, @LEDThread, vParData, 0, ThreadID);
sololie 2013-07-03
  • 打赏
  • 举报
回复
CreateThread创建线程后,必须把delphi的系统全局变量IsMultiThread设为TRUE,线程结束后它系统会自动把IsMultiThread设回FALSE。但是,最好的方法就是用抛弃CreateThread,而用BeginThread来创建线程,BeginThread内存会把IsMultiThread:=True。 你的代码做下面修改 function LEDThread(AParData: PParData): Boolean; // stdcall; 去掉 begin ..... DeleteObject(oldpBitmap); Dispose(AParData); // 这里释放内存 Sleep(100); //这个sleep不能太大,或者去掉这个sleep Result := True; end; 改好后,你再继续测试个把小时看看
xhz8000 2013-07-03
  • 打赏
  • 举报
回复
确实你分配的New(vParData); 内存也不见在那里释放??
sololie 2013-07-03
  • 打赏
  • 举报
回复
内存泄露,泄到不能泄就歇菜了
xhz8000 2013-07-03
  • 打赏
  • 举报
回复
procedure TForm1.Button1Click(Sender: TObject); begin IsMultiThread := TRUE; //这里加也行 Timer1.Enabled:=True;//启动定时器 end;
xhz8000 2013-07-03
  • 打赏
  • 举报
回复
在定时器里面的第一行加上: IsMultiThread := TRUE;
请先阅读帮助文档:http://ismyway.com/help [2009.1.1] Ver 3.2.26 ※如果安装提示证书过期或无法安装,请在手机上将时间改为2008.8.8,安装设置完成后再将日期改回即可!※ 增加天语的按键映射 增加三星的背景灯控制功能(该功能未在真机上测试过) 删除图片浏览中的部分功能,由于这部分功能需要较大的内存,导致在大部分手机上无法完成,同时也引起背景图片无法设置成功 触摸屏用户可以不再受滚动条限制,在屏幕上任意地方都可以进行拖动 选择键盘映射为其它时无法再次更改的BUG 用户输入的颜色值无法保存的BUG 修正英文单词分词时会多添加一个空行的BUG 繁体语言措词上的修正 阅读设置中增加一个“文件缓存”选项,默认情况下是开启的,在NOKIA手机上会提高UMD等文件的表现,但由于测试并不充足,如果程序经常在阅读时出错,请关闭该选项(其它手机是否开启该选项并无明显的影响) 修正编辑文件后无法保存的BUG [2008.10.27] Ver 3.2.24 ※如果安装提示证书过期或无法安装,请在手机上将时间改为2008.8.8,安装设置完成后再将日期改回即可!※ 改进的颜色选择方式 允许用户重新选择键盘映射 HTML阅读时的错误 进一步完善编辑功能(仍有少许BUG,请继续反馈,谢谢) 新建文件后自动跳转到编辑中 改进的文件操作方式,速度轻微提升 UMD速度明显提升,并且减少内存占用,特别是在NOKIA手机上,表现提升超过600% 改进的输入框模式,以使得能适应更多的手机如天语等 [2008.10.21] Ver 3.2.23 为了提高运行效率,以下功能在LITE上将被取消(自定义欢迎页问候语;欢迎页背景图) 取消了JAR的支持,提高运行效率 修正打开大ZIP文件时的内存溢出错误 ·修正:  自动滚屏到末尾时,滚屏功能将停止 [2008.10.4] Ver 3.2.22 暂时删除了播放功能及网络相关的功能,由于以上两项功能一直没有能稳定下来,故暂时删除 增强了ZIP功能,支持带文件夹结构的ZIP/JAR文件 (对于大部分JAR电子书都,可以从文件管理器中找到非.class结尾的文件,并且选择打开为UNICODE/TXT阅读) (对于NOKIA手机及其它部分手机,由于安全策略的限制,在Anyview的文件管理器中无法查看后缀为.jar的文件) 自定义问候语(系统路径下dictum.rc文件,格式参见jar包中的dictum.rc文件,保存时使用UTF-8编码,可写条目为0~9/a~z/A~Z,置空时表示不显示问候语) ·修正:  0键在各偏好中切换时亮度混乱的问题  部分手机上无法新建文件夹 [2008.9.11] Ver 3.2.21 修正动画参数无法保存的BUG 动画效果不再对阅读翻页有作用 [2008.8.29] Ver 3.2.21 可将正在阅读的内容通过短信与好友分享 增加一种新的滚屏方式:波浪,同时,阅读时3键不再使用默认的像素滚屏,而会使用最后一次使用的滚屏方式 任何可用的外置字库都可以作为内置字库存在,在jar包中存在dot.font会被当为内置字库加载 加快大文件的打开速度,特别是对于NOKIA手机,S60上,打开20M文件,97%左右的位置不超过15秒 允许用户打开动画效果 ·M600/P990/P1/W950  修正键盘映射时“内存不足”的BUG ·E680/A780  选中后台播放后无法启动的BUG [2008.7.30] Ver 3.2.20 调整部分索爱手机上背景灯控制的逻辑 修正看图片时按0键出错的BUG 旋转屏幕引起的字外出 打开LRC最后出错 阅读到尾部弹出“上一个/下一个”窗口中的文件名过长不刷新的问题 偏好切换时亮度混乱的问题 在NOKIA上,当系统路径设置为根目录是无法启动的BUG E398上可以开关键盘灯 UIQ系统在退出时可以保持亮度 索爱上按“返回”键后导致阅读出现白屏的BUG 阅读时切换屏幕方向导致字体超出屏幕的BUG 欢迎屏幕上的日期使用中文显示 如果使用触屏手机,跳转改为进度条模式,以方便触屏操作 系统路径下如果存在bg.png文件,则会作为欢迎界面的背景图片显示(右下角) 减少跳转及翻页中出现乱码的机率 提高阅读时绘图效率,滚屏效率同样提高 播放时,暂停会导致声音爆至最大的BUG 内置“忘记月亮”制作的两款主题《典雅红》《黑橙》,并且更换主题不再要求退出 文件管理器中支持“剪切”功能 文件管理器中新增转换UMD为TXT的功能(解开操作,解开2无效!) 增加了编辑功能(尽管没有限制文件大小,但请别编辑过大的文件,另外,为了提高速度,不进行全文排版,有时候表现可能会有些不习惯),以后会进一步完善 启动时,会自动识别NOKIA、SONYER

16,748

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 语言基础/算法/系统设计
社区管理员
  • 语言基础/算法/系统设计社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧