结束线程总 报System Error Code 6 句柄无效代码如下
-------
unit ChoseUnt;procedure TChoseFrm.Label4Click(Sender: TObject);
var
  Frm: TOutDataFrm;
begin
  FormTitle := '电子报税数据导出';
  Frm := TOutDataFrm.Create(Self);
  try
    ChoseNum := 4;
    Frm.ShowModal;
  finally
    Frm.Close;
  end;
end;
-------------
unit OutDataUnt;procedure TOutDataFrm.Button3Click(Sender: TObject);
begin
  if ThreadUnt.PubThred <> nil then 
  begin
    ThreadUnt.PubThred.Terminate;
    ThreadUnt.PubThred.WaitFor;
    ThreadUnt.PubThred.Free;
  end;
  Button3.Enabled := False;
end;
procedure TOutDataFrm.ProcOutSearchData_dzbs;
var
  DateFileStr, DateStr, BgDataStr, InsertSqlStr, EdDataStr, StrErr,
    StrMsg, FieldStr, WrFileStr, selSql, s, ridStr: string;
  AryNum, FieldNum, OdNum, i, p: Integer;
  EveyNum: Double;
  Qytmp: TADOQuery;
  Ftext: TextFile;
begin
  CommFuncUnt.ProcWriteFile('***************************************************************'
    + FuncGetDateStr, CommFuncUnt.FuncGetLogFile(Unit_DbtoFLogFileName));
  CommFuncUnt.ProcWriteFile('开始导出表returnreceipt数据   时间:' +
    FuncGetDateStr, CommFuncUnt.FuncGetLogFile(Unit_DbtoFLogFileName));  DateStr := copy(FuncGetVersion, 0, 8);
  DateFileStr := FuncGetVersion;  EveyNum := AllDataNum / 1000;
  p := pos('.', FloattoStr(EveyNum));
  s := copy(FloattoStr(EveyNum), 1, p - 1);
  try
    OdNum := StrToInt(s);
  except
    on e:
    Exception do
    begin
      CommFuncUnt.ProcWriteFile('数据初试化失败',
        CommFuncUnt.FuncGetLogFile(Unit_DbtoFLogFileName));
      CommFuncUnt.ProcWriteFile('***************************************************************'
        + FuncGetDateStr, CommFuncUnt.FuncGetLogFile(Unit_DbtoFLogFileName));
      StatusBar1.Panels[0].Text := '数据初试化失败';
      button2.Enabled := True;
      Screen.cursor := crDefault;
      Exit;
    end;
  end;
  Qytmp := DataModuleUnt.DataModule1.QyTmp1; ;  AryNum := 0;
  /////开始数据导入
  //////打开文件
  AssignFile(Ftext, Edit5.Text + '\returnreceipt_' + DateFileStr + '.txt');
  rewrite(Ftext);
  append(Ftext);
  ///////写入导出文件头
  BgDataStr := 'BEGIN' + #13#10;
  BgDataStr := BgDataStr + IntToStr(AllDataNum) + '~~returnreceipt' + #13#10;
  BgDataStr := BgDataStr + '{' + #13#10;
  BgDataStr := BgDataStr + '0~~' + IntToStr(AllDataNum + 2) +
    '~~returnreceipt~~电子报税回执数据' + #13#10;
  BgDataStr := BgDataStr + '1~~' + sjbh + '~~' + sjmc + '~~' + DateStr + #13#10;
  BgDataStr := BgDataStr + '2~~3~~' + IntToStr(AllDataNum + 2);
  //ProcWriteFile(BgDataStr, Edit5.Text + '\fapsj_' + DateFileStr + '.txt');
  writeln(Ftext, BgDataStr);
  //ProgressBar1.Max := length(SearchDataAry);
  ProgressBar1.Max := AllDataNum;  ///////写入导出文件体
  for i := 0 to odNum do
  begin
    if i = 0 then
    begin
      selSql := 'SELECT substr(rowid||jitbm,0,18) as id, nasrnm, jitbm, youjrq, banbh, suosrq,';
      selSql := selSql + 'biaom, shuizmc, fajrdz, shoujrdz, subject, msgtext,';
      selSql := selSql + 'send_flag, shangcbz  ';
      selSql := selSql + 'FROM returnreceipt where rownum<1001';
    end
    else
    begin
      selSql := 'SELECT substr(rowid||jitbm,0,18) as id, nasrnm, jitbm, youjrq, banbh, suosrq,';
      selSql := selSql + 'biaom, shuizmc, fajrdz, shoujrdz, subject, msgtext,';
      selSql := selSql + 'send_flag, shangcbz  ';
      selSql := selSql + 'FROM returnreceipt where rownum<1001 and rowid>''' +
        ridStr + '''';
    end;
    if AddSqlStr <> '' then
    begin
      Selsql := Selsql + ' and ' + AddSqlStr;
    end;
    //////--------------选出要导出的数据
    if not CommFuncUnt.FuncExecSql(selSql, Qytmp, True, StrErr) then
    begin
      StrMsg := '执行SQL:' + selSql + '语句出错,错误原因:' + StrErr;
      FuncShowMessage(Handle, StrMsg, 2);
      CommFuncUnt.ProcWriteFile('数据初试化失败:' + StrMsg,
        CommFuncUnt.FuncGetLogFile(Unit_DbtoFLogFileName));
      CommFuncUnt.ProcWriteFile('***************************************************************'
        + FuncGetDateStr, CommFuncUnt.FuncGetLogFile(Unit_DbtoFLogFileName));
      StatusBar1.Panels[0].Text := '数据初试化失败';
      button2.Enabled := True;
      Screen.cursor := crDefault;
      Exit;
    end;
    WrFileStr := '';
    try
      while not Qytmp.EOF do
      begin
        FieldStr := IntToStr(aryNum + 3) + '~~';
        for FieldNum := 1 to Qytmp.FieldCount - 1 do
        begin
          FieldStr := FieldStr + Qytmp.Fields[FieldNum].AsString + '~~';
        end;        FieldStr := copy(FieldStr, 0, length(FieldStr) - 2);
        writeln(Ftext, FieldStr);
        //WrFileStr := WrFileStr + FieldStr + #13#10;
        InsertSqlStr :=
          'update returnreceipt set shangcbz=decode(shangcbz,null,1,shangcbz+1) where rowid= ''' +
          Qytmp.Fields[0].AsString + '''';        if not CommFuncUnt.FuncExecSql(InsertSqlStr,
          DataModuleUnt.DataModule1.QyTmp2, False, StrErr) then
        begin
          StrMsg := '执行SQL:' + InsertSqlStr + '语句出错,错误原因:' + StrErr;
          FuncShowMessage(Handle, StrMsg, 2);
          button1.Enabled := True;
          Screen.cursor := crDefault;
          CommFuncUnt.ProcWriteFile('导出表returnreceipt数据失败   时间:' +
            FuncGetDateStr, CommFuncUnt.FuncGetLogFile(Unit_DbtoFLogFileName));
          CommFuncUnt.ProcWriteFile('失败原因:' + StrMsg,
            CommFuncUnt.FuncGetLogFile(Unit_DbtoFLogFileName));
          CommFuncUnt.ProcWriteFile('***************************************************************'
            + FuncGetDateStr, CommFuncUnt.FuncGetLogFile(Unit_DbtoFLogFileName));
          Closefile(Ftext);
          DeleteFile(Edit5.Text + '\returnreceipt_' + DateFileStr + '.txt');
          Exit;
        end;
        inc(AryNum);
        ProgressBar1.Position := AryNum;
        StatusBar1.SimpleText := '正在导出第' + IntToStr(AryNum) + '条数据';
        FieldStr := '';
        ridStr := Qytmp.FieldByName('id').AsString;
        Qytmp.Next;        //////退出
        if ThreadUnt.PubThred.Terminated then
        begin
          Closefile(Ftext);
          Qytmp.Close;
          DeleteFile(Edit5.Text + '\returnreceipt_' + DateFileStr + '.txt');
          button1.Enabled := True;
          Screen.cursor := crDefault;
          StatusBar1.SimpleText := '导出中断';
          ProgressBar1.Position := 0;
          Exit;
        end;
        //////
      end;
    except
      on e:
      Exception do
      begin
      end;
    end;
  end;
  Qytmp.Close;  EdDataStr := EdDataStr + '}' + #13#10;
  EdDataStr := EdDataStr + 'END';
  //ProcWriteFile(EdDataStr, Edit5.Text + '\fapsj_' + DateFileStr + '.txt');
  writeln(Ftext, EdDataStr);
  ////////////////数据导出完毕
  StatusBar1.Panels[0].Text := '共导出' + IntToStr(AllDataNum) + '条数据';
  closefile(Ftext);
  Screen.cursor := crDefault;
  button2.Enabled := True;
  CommFuncUnt.ProcWriteFile('共导出' + IntToStr(AllDataNum) + '条数据',
    CommFuncUnt.FuncGetLogFile(Unit_DbtoFLogFileName));
  CommFuncUnt.ProcWriteFile('导出表returnreceipt数据结束   时间:' +
    FuncGetDateStr, CommFuncUnt.FuncGetLogFile(Unit_DbtoFLogFileName));
  CommFuncUnt.ProcWriteFile('***************************************************************'
    + FuncGetDateStr, CommFuncUnt.FuncGetLogFile(Unit_DbtoFLogFileName));
end;

解决方案 »

  1.   

    终止线程最好不要用
    Terminate;
    ThreadUnt.PubThred.WaitFor;
    ThreadUnt.PubThred.Free;
    这样的。
    如果要强制kill这样写线程的FreeOnTerminate设成False
    然后Thread.Free;最好的方法是
    线程的FreeOnTerminate设成True
    然后然后在线程中经常判断Terminated
    终止线程用Thread.Terminate
      

  2.   

    我是这样的啊 很奇怪啊constructor ThredUnt.create(s: string);
    begin
      inherited Create(false);
      PrStr := s;
      Self.FreeOnTerminate := true;
    end;destructor ThredUnt.destroy;
    begin
      //PubThred := nil;
      inherited destroy;
    end;procedure ThredUnt.DoTerminate;
    begin
      inherited;
      PubThred := nil;
    end;procedure ThredUnt.Execute;
    begin
      if PrStr = 'SearchData' then
        OutDatafrm.ProcSearchData
      else if PrStr = 'OutSearchData' then
        OutDatafrm.ProcOutSearchData
      else if PrStr = 'DatatoDb' then
        InDatafrm.ProcDataToDb
      else if PrStr = 'SearchData_dzbs' then
        OutDatafrm.ProcSearchData_dzbs
      else if PrStr = 'OutSearchData_dzbs' then
        OutDatafrm.ProcOutSearchData_dzbs
      else if PrStr = 'DatatoDb_dzbs' then
        InDatafrm.ProcDataToDb_dzbs
      else if PrStr = 'SelDelData' then
        DelDatafrm.ProcSelDelData
      else if PrStr = 'DelSelData' then
        DelDatafrm.ProcDelSelData
      else
        PubThred := nil;  { Place thread code here }
    end;
      

  3.   

    你应该把线程的FreeOnTerminate设成False
    然后Thread.Free;
    不用terminate然后waitfor
    虽然该方法不大好,但是至少不会报错最好的方法是线程自己释放,那么你的
    ProcOutSearchData_dzbs
    ProcSelDelData
    这些过程就要判断thread.Terminated,如果Terminated,就要exit退出,这样线程就自己释放了
      

  4.   

    FreeOnTerminate设成False那么线程不是自动释放 那么执行结束后 释放不掉怎么办啊??
      

  5.   

    线程不是自动释放但是你调用
    Thread.Free;
    就手工释放了,否则系统自动释放的时候会报错,因为已经被你手工释放了