Delphi 关于内存错误的疑问

m0_37551303 2019-05-27 10:42:59
小弟写了这么一段。总是莫名其妙的提示内存错误。请各位大大帮帮看看到底是哪里的问题

procedure TBackup.Execute;
const
Model = 'mm-dd hh:nn:ss';
var
FileList: TStrings;
FindResult: Integer;
FSearchRec: TSearchRec;
Dir, Volume, Time: string;
Handle: Thandle;
begin
FreeOnTerminate := True;
Dir := lj2 + '\ConanSandbox\Saved\';
FileList := TStringList.Create;
try
Form1.ListBox1.Clear;
FindResult := FindFirst(Dir + '*.db', faAnyFile + faDirectory, FSearchRec);
while FindResult = 0 do
begin
if Length(LowerCase(FSearchRec.Name)) = 16 then
begin

Handle := Fileopen(Dir + LowerCase(FSearchRec.Name), 0);
Time := FormatdateTime(Model, Filedatetodatetime(Filegetdate(Handle)));
Fileclose(Handle);
// Time := FormatdateTime(Model, FileDateToDateTime(FileAge(Dir + LowerCase(FSearchRec.Name))));
Volume := IntToStr(FileSizeByName(Dir + FSearchRec.Name));
FileList.Add(LowerCase(FSearchRec.Name) + ' Time:' + Time + ' FileSize:' + Volume);
end;
FindResult := FindNext(FSearchRec);
end;
FindClose(FSearchRec);

FindResult := FindFirst(Dir + '*.db', faAnyFile + faDirectory, FSearchRec);
while FindResult = 0 do
begin
if Length(LowerCase(FSearchRec.Name)) = 17 then
begin
Handle := Fileopen(Dir + LowerCase(FSearchRec.Name), 0);
Time := FormatdateTime(Model, Filedatetodatetime(Filegetdate(Handle)));
Fileclose(Handle);
// Time := FormatdateTime(Model, FileDateToDateTime(FileAge(Dir + LowerCase(FSearchRec.Name))));
Volume := IntToStr(FileSizeByName(Dir + FSearchRec.Name));
FileList.Add(LowerCase(FSearchRec.Name) + ' Time:' + Time + ' FileSize:' + Volume);
end;
FindResult := FindNext(FSearchRec);
end;
Form1.ListBox1.Items := FileList;
except
Form1.BackTime.Enabled := False;
writeWorkLog('错误:#300001');//自己写的日志,记录错误出现的时间。
end;
FindClose(FSearchRec);
FileList.Free;
end;



各位大大帮帮啊。
...全文
183 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
m0_37551303 2019-05-30
  • 打赏
  • 举报
回复
引用 8 楼 早打大打打核战争 的回复:
你这还是在非主线程中操作VCL组件,是不安全的,也可能工作正常,看时机。
就这段代码的功能看,你可以只把下载文件放在单独的线程中,其中设置下载状态(比如用全局变量),然后主线程读下载状态,更新界面显示。
业务逻辑和UI分离是一个好的设计风格,如果你觉得繁琐的话,可以用异步调用:
Form1.BeginInvoke(
procedure
begin
StatusBar1.Panels[0].Text := '开始下载...';
BitBtn1.Enabled := False;
BitBtn2.Enabled := False;
end);
或者用Synchronize也可以,Synchronize实际相当于EndInvoke,被调用代码结束前会一直阻塞Synchronize后面的代码


太感谢您了。
  • 打赏
  • 举报
回复
你这还是在非主线程中操作VCL组件,是不安全的,也可能工作正常,看时机。
就这段代码的功能看,你可以只把下载文件放在单独的线程中,其中设置下载状态(比如用全局变量),然后主线程读下载状态,更新界面显示。
业务逻辑和UI分离是一个好的设计风格,如果你觉得繁琐的话,可以用异步调用:
Form1.BeginInvoke(
procedure
begin
StatusBar1.Panels[0].Text := '开始下载...';
BitBtn1.Enabled := False;
BitBtn2.Enabled := False;
end);
或者用Synchronize也可以,Synchronize实际相当于EndInvoke,被调用代码结束前会一直阻塞Synchronize后面的代码
BlueStorm 2019-05-28
  • 打赏
  • 举报
回复
不能在线程里面直接操作VCL,如下面的语句是不行的: Form1.ListBox1.Items := FileList;
m0_37551303 2019-05-28
  • 打赏
  • 举报
回复
引用 5 楼 早打大打打核战争 的回复:
这个是关键:
2. Form1.ListBox1.Items := FileList;应该是Form1.ListBox1.Items.Assign(FileList); 否则FileList.Free;之后就出问题了


大大,那我这么写匿名线程也是有问题的了?


TThread.CreateAnonymousThread(
procedure
begin
StatusBar1.Panels[0].Text := '开始下载...';
BitBtn1.Enabled := False;
BitBtn2.Enabled := False;
if DownloadFile(Dourl, lj1 + '\Temp.zip') then
begin
StatusBar1.Panels[0].Text := '下载完成...';
zip := TZipFile.Create;
zip.Open(lj1 + '\Temp.zip', TZipMode.zmRead);
zip.ExtractAll(lj1 + '\');
zip.Free;
DeleteFile(lj1 + '\Temp.zip');
StatusBar1.Panels[0].Text := StatusBar1.Panels[0].Text + ' steamcmd.exe 解压完成!';
BitBtn1.Enabled := True;
BitBtn2.Enabled := True;
end
else
begin
StatusBar1.Panels[0].Text := 'steamcmd.zip 下载失败!';
end;
if not SFindProcess('steamcmd.exe') then
begin
InstaUpdaSe;
InstaTime.Enabled := True;
IUName := 1;
end;
end).Start;
m0_37551303 2019-05-28
  • 打赏
  • 举报
回复
引用 5 楼 早打大打打核战争 的回复:
这个是关键:
2. Form1.ListBox1.Items := FileList;应该是Form1.ListBox1.Items.Assign(FileList); 否则FileList.Free;之后就出问题了


那比如说Timer控件的开启和关闭呢?也会出问题吗?
  • 打赏
  • 举报
回复
这个是关键:
2. Form1.ListBox1.Items := FileList;应该是Form1.ListBox1.Items.Assign(FileList); 否则FileList.Free;之后就出问题了
m0_37551303 2019-05-28
  • 打赏
  • 举报
回复
小弟我不想例子直接赋值,我想知道问题原因。如何处理这种错误。楼上的大大能说的详细一点吗?比如说子线程在写的过程中需要注意什么,主线程中的VCL应该如何给子线程操作呢?感激不尽啊~
m0_37551303 2019-05-28
  • 打赏
  • 举报
回复
引用 2 楼 早打大打打核战争 的回复:
这代码写的一锅粥~~~
1. 在非主线程中操作VCL组件是不安全的,可以使用Synchronize方法,或者异步调用(TComponent.BeginInvoke/EndInvoke)方法
2. Form1.ListBox1.Items := FileList;应该是Form1.ListBox1.Items.Assign(FileList); 否则FileList.Free;之后就出问题了
3. if Length(LowerCase(FSearchRec.Name)) = 16 then和if Length(LowerCase(FSearchRec.Name)) = 17 then的内部代码一样,你就不能合并一下么


主要是没有规律的报内存错误。你的意思是不要在线程内直接赋值控件吗?
  • 打赏
  • 举报
回复
这代码写的一锅粥~~~
1. 在非主线程中操作VCL组件是不安全的,可以使用Synchronize方法,或者异步调用(TComponent.BeginInvoke/EndInvoke)方法
2. Form1.ListBox1.Items := FileList;应该是Form1.ListBox1.Items.Assign(FileList); 否则FileList.Free;之后就出问题了
3. if Length(LowerCase(FSearchRec.Name)) = 16 then和if Length(LowerCase(FSearchRec.Name)) = 17 then的内部代码一样,你就不能合并一下么

1,184

社区成员

发帖
与我相关
我的任务
社区描述
Delphi Windows SDK/API
社区管理员
  • Windows SDK/API社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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