这是一个多线程的程序,
把一个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;

解决方案 »

  1.   

    照这个AV错误的意思,是你访问一个并不存在的对象。
    就你贴出来这些代码,看不出有什么问题,因为你线程的那个单元代码没贴上来。还有,检查一下NotifyThreadsToQuit这个远程。
    KillTask(ExtractFileName(程序.程序名)); 这里确定没错?是中文?
      

  2.   


    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.
      

  3.   

    比较长,不想仔细看。
    但有一点比较明显的问题:
    线程里面如果要访问主界面(主线程)上的控件,不应该直接用,否则可能会引起死锁,因为有可能N个线程同时访问一个控件。结果有可能引起AV错误,或者界面死掉。
    建议用信号量,或者用Synchronize
    把需要访问主界面上控件的那些代码写在一个或N个独立的过程里(线程内),假定Proc1,然后在线程内调用:Synchronize(Proc1);作用是让主线程去执行这个线程内的Proc1
    具体怎么做,网上都有例子的。
      

  4.   

    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(程序.程序路径+程序.输入文件名);

    把上面红色部分加一下进入临界区和退出临界区的操作,不要直接使用,否则会出问题
      

  5.   

    Up
    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(程序.程序路径+程序.输入文件名); 
    把上面红色部分加一下进入临界区和退出临界区的操作,不要直接使用,否则会出问题