这是一个多线程的程序,
把一个Procedure执行的东西移到新建的线程之前还是好好的,新建一个线程后
在程序关闭后,或运行当中出现错误,提示为:
Access violation at address 00000000.Read of address 00000000. 主程序Unit的开头:
unit Master;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, DynamicSkinForm, SkinData, SkinCtrls, StdCtrls, SkinBoxCtrls,
spSkinShellCtrls, Mask, SkinExCtrls, FileSystemWatcher, ShellAPI, TLHelp32,
spMessages, ExtCtrls, JustDoIt;{在这里定义了JustDoIt线程Unit}开始执行任务键:procedure TForm1.spSkinButton2Click(Sender: TObject);
Var
MyThread:TMyThread;
begin
MyThread:=TMythread.Create(True);
MyThread.FreeOnTerminate:=False;
MyThread.Interval:=100;
MyThread.Resume;
NotifyThreadsToQuit;
end;"取消"键事件:
procedure TForm1.spSkinButton3Click(Sender: TObject);
begin
NotifyThreadsToQuit;
KillTask(ExtractFileName(程序.程序名));
spSkinAnimateGauge1.StopAnimation;
end;
把一个Procedure执行的东西移到新建的线程之前还是好好的,新建一个线程后
在程序关闭后,或运行当中出现错误,提示为:
Access violation at address 00000000.Read of address 00000000. 主程序Unit的开头:
unit Master;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, DynamicSkinForm, SkinData, SkinCtrls, StdCtrls, SkinBoxCtrls,
spSkinShellCtrls, Mask, SkinExCtrls, FileSystemWatcher, ShellAPI, TLHelp32,
spMessages, ExtCtrls, JustDoIt;{在这里定义了JustDoIt线程Unit}开始执行任务键:procedure TForm1.spSkinButton2Click(Sender: TObject);
Var
MyThread:TMyThread;
begin
MyThread:=TMythread.Create(True);
MyThread.FreeOnTerminate:=False;
MyThread.Interval:=100;
MyThread.Resume;
NotifyThreadsToQuit;
end;"取消"键事件:
procedure TForm1.spSkinButton3Click(Sender: TObject);
begin
NotifyThreadsToQuit;
KillTask(ExtractFileName(程序.程序名));
spSkinAnimateGauge1.StopAnimation;
end;
就你贴出来这些代码,看不出有什么问题,因为你线程的那个单元代码没贴上来。还有,检查一下NotifyThreadsToQuit这个远程。
KillTask(ExtractFileName(程序.程序名)); 这里确定没错?是中文?
unit Handle;
interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, DynamicSkinForm, SkinData, SkinCtrls, StdCtrls, SkinBoxCtrls,
spSkinShellCtrls, Mask, SkinExCtrls, FileSystemWatcher, ShellAPI, TLHelp32,
spMessages, ExtCtrls;
Type
TTextThread = Class(TThread)
public
Procedure Close;
Private Protected
Function Kindi0(number:integer):String;
Function Kindi1(number:integer):String;
Function Kindi2(number:integer):String;
Function Kindi3(number:integer):String;
Function Kindo0(number:integer):String;
Function Kindo1(number:integer):String;
Function Kindo2(number:integer):String;
Function Kindo3(number:integer):String;
Procedure Execute; Override;
Procedure FC;
end;implementationuses Unit1, execute;
Function TTextThread.Kindi0(number:integer):string;
begin
result:=Unit1.Form1.数据.输入文件名+IntToStr(number)+'.'+Unit1.Form1.数据.输入文件名后缀;
end;Function TTextThread.Kindi1(number:integer):String;
begin
result:=Unit1.Form1.数据.输入文件名+'.'+Unit1.Form1.数据.输入文件名后缀+IntToStr(number);
end;Function TTextThread.Kindi2(number:integer):String;
begin
result:=IntToStr(number)+Unit1.Form1.数据.输入文件名+'.'+Unit1.Form1.数据.输入文件名后缀;
end;Function TTextThread.Kindi3(number:integer):String;
begin
result:=Unit1.Form1.数据.输入文件名+'.'+IntToStr(number)+Unit1.Form1.数据.输入文件名后缀;
end;Function TTextThread.Kindo0(number:integer):string;
begin
result:=Unit1.Form1.数据.输出文件名+IntToStr(number)+'.'+Unit1.Form1.数据.输出文件名后缀;
end;Function TTextThread.Kindo1(number:integer):String;
begin
result:=Unit1.Form1.数据.输出文件名+'.'+Unit1.Form1.数据.输出文件名后缀+IntToStr(number);
end;Function TTextThread.Kindo2(number:integer):String;
begin
result:=IntToStr(number)+Unit1.Form1.数据.输出文件名+'.'+Unit1.Form1.数据.输出文件名后缀;
end;Function TTextThread.Kindo3(number:integer):String;
begin
result:=Unit1.Form1.数据.输出文件名+'.'+IntToStr(number)+Unit1.Form1.数据.输出文件名后缀;
end;
Procedure TTextThread.Execute;
var
name:String;
i:Integer;
begin
FreeOnTerminate := True;
with Unit1.Form1 do
begin
if 数据量B>数据量E then
for I := 数据量E downto 数据量B do
begin
if Terminated=true then Break;
spSkinMemo1.Lines.Add('这是第'+IntToStr(i)+'个数据包');
thisc:=i;
case 类型 of
0:name:=Kindi0(i);
1:name:=Kindi1(i);
2:name:=Kindi2(i);
3:name:=Kindi3(i);
end;
memo.Lines.LoadFromFile(数据.数据文件夹路径+name);
memo.Lines.SaveToFile(程序.程序路径+程序.输入文件名);
before:=Now;
SText.Caption:='正在等待程序';
ChDir(程序.程序路径);
waitexecute(程序.程序名,程序.程序路径);
spSkinMemo1.Lines.Add('用时'+FormatDateTime('ss.zzz',Now-before)+'秒');
fc;
spSkinMemo1.Lines.Add('=========================================');
SText.Caption:='';
end
else
for I := 数据量B to 数据量E do
begin
if Terminated=true then Break;
spSkinMemo1.Lines.Add('这是第'+IntToStr(i)+'个数据包');
thisc:=i;
case 类型 of
0:name:=Kindi0(i);
1:name:=Kindi1(i);
2:name:=Kindi2(i);
3:name:=Kindi3(i);
end;
memo.Lines.LoadFromFile(数据.数据文件夹路径+name);
memo.Lines.SaveToFile(程序.程序路径+程序.输入文件名);
before:=Now;
SText.Caption:='正在等待程序';
ChDir(程序.程序路径);
waitexecute(程序.程序名,程序.程序路径);
spSkinMemo1.Lines.Add('用时'+FormatDateTime('ss.zzz',Now-before)+'秒');
fc;
spSkinMemo1.Lines.Add('=========================================');
SText.Caption:='';
end;
spSkinMemo1.Lines.Add('完成!');
spSkinButton3Click(nil);
Step:=FALSE;
end;
Close;
end;procedure TTextThread.FC;
var
str:string;
i:integer;
begin
with Unit1.Form1 do
begin
case 类型 of
0:str:=Kindo0(thisc);
1:str:=Kindo1(thisc);
2:str:=Kindo1(thisc);
3:str:=Kindo2(thisc);
end;
memo.Lines.LoadFromFile(程序.程序路径+程序.输出文件名);
batm.Lines.LoadFromFile(数据.数据文件夹路径+str); for i := memo.Lines.Count-1 downto 0 do
begin
if length(trim(memo.Lines[i]))=0 then memo.Lines.Delete(i)
else break;
end; for i := batm.Lines.Count-1 downto 0 do
begin
if length(trim(batm.Lines[i]))=0 then batm.Lines.Delete(i)
else break;
end; for I := 0 to Memo.Lines.Count - 1 do
begin
if memo.Lines[i]<>batm.Lines[i] then
begin
spSkinMemo1.Lines.Add('数据有误!');
spSkinMemo1.Lines.Add('该程序输出:');
spSkinMemo1.Lines.AddStrings(memo.Lines);
spSkinMemo1.Lines.Add('正确答案:');
spSkinMemo1.Lines.AddStrings(batm.Lines);
Exit;
end;
end;
spSkinMemo1.Lines.Add('数据通过测试!');
end;
end;Procedure TTextThread.Close;
begin
FreeOnTerminate:=FALSE;
Free;
end;end.
但有一点比较明显的问题:
线程里面如果要访问主界面(主线程)上的控件,不应该直接用,否则可能会引起死锁,因为有可能N个线程同时访问一个控件。结果有可能引起AV错误,或者界面死掉。
建议用信号量,或者用Synchronize
把需要访问主界面上控件的那些代码写在一个或N个独立的过程里(线程内),假定Proc1,然后在线程内调用:Synchronize(Proc1);作用是让主线程去执行这个线程内的Proc1
具体怎么做,网上都有例子的。
thisc:=i;
case 类型 of
0:name:=Kindi0(i);
1:name:=Kindi1(i);
2:name:=Kindi2(i);
3:name:=Kindi3(i);
end;
memo.Lines.LoadFromFile(数据.数据文件夹路径+name);
memo.Lines.SaveToFile(程序.程序路径+程序.输入文件名);
把上面红色部分加一下进入临界区和退出临界区的操作,不要直接使用,否则会出问题
Up
spSkinMemo1.Lines.Add('这是第'+IntToStr(i)+'个数据包');
thisc:=i;
case 类型 of
0:name:=Kindi0(i);
1:name:=Kindi1(i);
2:name:=Kindi2(i);
3:name:=Kindi3(i);
end;
memo.Lines.LoadFromFile(数据.数据文件夹路径+name);
memo.Lines.SaveToFile(程序.程序路径+程序.输入文件名);
把上面红色部分加一下进入临界区和退出临界区的操作,不要直接使用,否则会出问题