我在关闭多线程程序之后,系统出错:
1.Exception EOSError in module project1.exe at 0000E3Ae.system error code:1400 无效的窗口句柄.
2.Runtime error 216 at 7C921010以下是我的代码:
unit UMain;interfaceuses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, DB, ADODB, Grids, DBGrids, StdCtrls, ExtCtrls,excel2000,OleServer,comObj,
  DBGridEh, Unit2;type
  TMain = class(TForm)
    ADOQuery1: TADOQuery;
    DataSource1: TDataSource;
    DBGrid1: TDBGridEh;
    SaveDialog1: TSaveDialog;
    Panel1: TPanel;
    Button1: TButton;
    OpenDialog1: TOpenDialog;
    Button3: TButton;
    ADOQuery2: TADOQuery;
    Label1: TLabel;
    Edit1: TEdit;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);    procedure Button3Click(Sender: TObject);
    procedure Edit1KeyPress(Sender: TObject; var Key: Char);
    procedure Button2Click(Sender: TObject);  private
    procedure ThreadDone(Sender:TObject);
    { Private declarations }
  public
    { Public declarations }
    ExcelToSQL:ImportExcel;
  end;var
  Main: TMain;implementationuses UDM, Unit1;{$R *.dfm}procedure TMain.Button1Click(Sender: TObject);
var
fname,moldid:string;
excelid:variant;
ColumnCount,sheetcount,i,j,k:integer;
begin
//Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Documents and Settings\Administrator\桌面\6月份外加工费用统计表.xls;Extended Properties=Excel 8.0;Persist Security Info=Falseif (Edit1.Text='') then
begin
   MessageDlg('输入的内容为空',mtwarning,[mbOK],0);
   exit;
end;
if OpenDialog1.Execute then
   fname:=OpenDialog1.FileName
else exit;ExcelToSQL:=ImportExcel.Create(fname);
//ExcelToSQL.Resume;
//ExcelToSQL.OnTerminate:=ThreadDone;
end;procedure TMain.FormCreate(Sender: TObject);
begin
  ADOQuery1.Active:=True;
end;procedure TMain.Button3Click(Sender: TObject);
begin
 ADOQuery1.Requery();
end;procedure TMain.Edit1KeyPress(Sender: TObject; var Key: Char);
begin
if not (key in ['0'..'9',#8]) then key:=#0;
end;procedure TMain.Button2Click(Sender: TObject);
begin
  with TForm1.Create(self) do
       Show;
end;procedure TMain.ThreadDone(Sender:TObject);
begin
//  showmessage('success');
end;end.unit Unit2;interfaceuses
  Classes,ADODB,comobj,excel2000,oleserver,SysUtils;type
  ImportExcel = class(TThread)
  private
    Fullfilename:string;
    ADOQuery1:TADOQuery;
    k:integer;
    procedure GetEditText;
    { Private declarations }
  protected
    procedure Execute; override;
  public
    Constructor Create(filename:string);
  end;implementationuses UMain,dialogs;{ Important: Methods and properties of objects in visual components can only be
  used in a method called using Synchronize, for example,      Synchronize(UpdateCaption);  and UpdateCaption could look like,    procedure ImportExcel.UpdateCaption;
    begin
      Form1.Caption := 'Updated in a thread';
    end; }{ ImportExcel }Constructor ImportExcel.Create(filename:string);
begin
  Fullfilename:=filename;
  Inherited Create(False);
end;procedure ImportExcel.GetEditText;
begin
  k:=StrToInt(Main.Edit1.text);
end;procedure ImportExcel.Execute;
var
   excelid:variant;
   i:integer;
begin
  { Place thread code here }
excelid:=Createoleobject('Excel.Application'); //1、创建连接
excelid.visible:=false;
excelid.workbooks.open(Fullfilename); //2、指定文件
Synchronize(GetEditText);Try
 try
  ADOQuery1:=TADOQuery.Create(nil);
  with ADOQuery1 do
  begin
    ConnectionString:='Provider=MSDASQL.1;Persist Security Info=True;User ID=wu;Data Source=mjgl';
    Close;
    SQL.Clear;
    SQL.Text:='select * from jgfy';
    Open;
  end;
for i:=3 to 1000 do  //最大行数1000
begin
    //判断是否结束
    if Trim(Excelid.WorkBooks[1].Worksheets[k].Cells[i,1].Value)<>'' then
    begin
      with ADOQuery1 do
      begin
        Append;
        FieldByName('rdate').Value:=Excelid.WorkBooks[1].Worksheets[k].Cells[i,1].Value;
        FieldByName('moldid').Value:=Excelid.WorkBooks[1].Worksheets[k].Cells[i,2].Value;
        FieldByName('gz').Value:=  Excelid.WorkBooks[1].Worksheets[k].Cells[i,3].Value;
        FieldByName('amount').Value:=  Excelid.WorkBooks[1].Worksheets[k].Cells[i,4].Value;
        FieldByName('fkfs').Value:=  Excelid.WorkBooks[1].Worksheets[k].Cells[i,5].Value;
        FieldByName('maker').Value:=  Excelid.WorkBooks[1].Worksheets[k].Cells[i,6].Value;
        FieldByName('jgs').Value:=  Excelid.WorkBooks[1].Worksheets[k].Cells[i,7].Value;
        FieldByName('memo').Value:=  Excelid.WorkBooks[1].Worksheets[k].Cells[i,8].Value;
        Post;
      end;
    end
      else break;
end; //for
except
  adoquery1.Free;
  excelid.quit;
  showmessage('导入出错!');
end;
finally
  excelid.quit;
  ADOQuery1.Free;
  showmessage('导入成功');
end;
end;end.

解决方案 »

  1.   

    另外还有一个问题:
    finally 
        excelid.quit; 
        ADOQuery1.Free; 
        showmessage( "导入成功 "); 
    我明明退出了EXCEL程序(excelid.quit) 但是在任务管理器中还是有很多EXCEL进程?
    这是怎么回事?
      

  2.   

    我没关闭线程?
    那应该怎么关闭线程?请教~~!
    我设了FreeOnTerminate:=True 
      

  3.   

    你在线程中 ShowMessage, 线程怎么可能运行结束?在线程代码中不要带对话框之类的操作,这是忠告!
      

  4.   

    线程已经被 ShowMessage 阻塞了!
      

  5.   

    用sendmessage还不是跟showmessage一样的
      

  6.   

    放个Memo或Label之类的,导入是否成功就改它们的值。
      

  7.   

    通过发送消息来知道是否导出成功。SendMessage(某个处理消息的handle,消息编号,参数1,参数2);
    例如:你可以用参数1=0表示成功.参数1=1表示失败.处理消息的函数:
    procedure  xx(var m:Tmessage); message 消息名;一旦接收到消息,就知道是成功了还是失败了.
      

  8.   

    如果有三个线程,一个操作失败,二个成功!那Label显示什么内容?
    就像迅雷一样,可下载多个文件,每个都可以显示其状态(成功还是不成功)!怎么做呢?
      

  9.   

    不是有个ReturnValue属性,可以返回值的,不过不知道怎么用.找不到相关例子~~~~~~~
      

  10.   

    mastersky:
    是不是要自定义一个消息??~~
      

  11.   

    mastersky:请问一下:这个消息的定义与现实是写在主程序单元中还是写在线程单元中?
      

  12.   

    mastersky:请问一下:这个消息的定义与现实是写在主程序单元中还是写在线程单元中?
    unit UMain;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, DB, ADODB, Grids, DBGrids, StdCtrls, ExtCtrls,excel2000,OleServer,comObj,
      DBGridEh, Unit2;
    Const
      UM_SUCCESS=WM_USER+100;
    type
      TMain = class(TForm)
        ADOQuery1: TADOQuery;
        DataSource1: TDataSource;
        DBGrid1: TDBGridEh;
        SaveDialog1: TSaveDialog;
        Panel1: TPanel;
        Button1: TButton;
        OpenDialog1: TOpenDialog;
        Button3: TButton;
        ADOQuery2: TADOQuery;
        Label1: TLabel;
        Edit1: TEdit;
        Button2: TButton;
        procedure Button1Click(Sender: TObject);
        procedure FormCreate(Sender: TObject);    procedure Button3Click(Sender: TObject);
        procedure Edit1KeyPress(Sender: TObject; var Key: Char);
        procedure Button2Click(Sender: TObject);  private
        ThreadsRuning:integer;
        procedure ThreadDone(Sender:TObject);
        procedure UMSuccess(var Msg:TMessage);message UM_SUCCESS;
        { Private declarations }
      public
        { Public declarations }
        ExcelToSQL:ImportExcel;
      end;var
      Main: TMain;implementationuses UDM, Unit1;{$R *.dfm}procedure TMain.UMSuccess(var Msg:TMessage);
    begin
    //add code here.
      if Msg.WParam=0 then showmessage('导入成功')
      else showmessage('导入失败');
    end;
    procedure TMain.Button1Click(Sender: TObject);
    var
    fname,moldid:string;
    excelid:variant;
    ColumnCount,sheetcount,i,j,k:integer;
    begin
    //Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Documents and Settings\Administrator\桌面\6月份外加工费用统计表.xls;Extended Properties=Excel 8.0;Persist Security Info=Falseif (Edit1.Text='') then
    begin
       MessageDlg('输入的内容为空',mtwarning,[mbOK],0);
       exit;
    end;
    if OpenDialog1.Execute then
       fname:=OpenDialog1.FileName
    else exit;ExcelToSQL:=ImportExcel.Create(fname);
    //ExcelToSQL.Resume;
    ExcelToSQL.OnTerminate:=ThreadDone;{
    try
    Screen.Cursor := crHourGlass;  //显示漏斗光标
    excelid:=Createoleobject('Excel.Application'); //1、创建连接
    excelid.visible:=false;
    //showmessage(fname);
    excelid.workbooks.open(fname); //2、指定文件
    adoquery1.Active:=true;
    k:=StrToInt(edit1.Text);
    //try
    //dm.ADOCon.BeginTrans  //开始一个事务
    for i:=3 to 1000 do  //最大行数1000
    begin
        //判断是否结束
        if Trim(Excelid.WorkBooks[1].Worksheets[k].Cells[i,1].Value)<>'' then
        begin
          with ADOQuery1 do
          begin
            Append;
            FieldByName('rdate').Value:=Excelid.WorkBooks[1].Worksheets[k].Cells[i,1].Value;
            FieldByName('moldid').Value:=Excelid.WorkBooks[1].Worksheets[k].Cells[i,2].Value;
            FieldByName('gz').Value:=  Excelid.WorkBooks[1].Worksheets[k].Cells[i,3].Value;
            FieldByName('amount').Value:=  Excelid.WorkBooks[1].Worksheets[k].Cells[i,4].Value;
            FieldByName('fkfs').Value:=  Excelid.WorkBooks[1].Worksheets[k].Cells[i,5].Value;
            FieldByName('maker').Value:=  Excelid.WorkBooks[1].Worksheets[k].Cells[i,6].Value;
            FieldByName('jgs').Value:=  Excelid.WorkBooks[1].Worksheets[k].Cells[i,7].Value;
            FieldByName('memo').Value:=  Excelid.WorkBooks[1].Worksheets[k].Cells[i,8].Value;
            Post;
          end;
        end
        else break;
    end;
    //dm.ADOCon.CommitTrans;
    //except
    //dm.ADOCon.RollbackTrans; //回滚
    //end; Screen.Cursor := crDefault;
     MessageDlg('数据导入成功!',mtInformation,[mbOK],0);
     excelid.quit;
    except
      excelid.quit;
      showmessage('导入出错!');
    end;
     }
    end;procedure TMain.FormCreate(Sender: TObject);
    begin
      ADOQuery1.Active:=True;
      ThreadsRuning:=0;
    end;procedure TMain.Button3Click(Sender: TObject);
    begin
     ADOQuery1.Requery();
    end;procedure TMain.Edit1KeyPress(Sender: TObject; var Key: Char);
    begin
    if not (key in ['0'..'9',#8]) then key:=#0;
    end;procedure TMain.Button2Click(Sender: TObject);
    begin
      with TForm1.Create(self) do
           Show;
    end;procedure TMain.ThreadDone(Sender:TObject);
    begin
      Inc(ThreadsRunning);
      if ThreadsRunning=3 then
      begin
         Button1.Enabled:=False;
         showmessage('Max');
      end;
    end;end.
    //线程单元,SendMessage这个函数包含在哪个单元中?
    unit Unit2;interfaceuses
      Classes,ADODB,comobj,excel2000,oleserver,SysUtils;type
      ImportExcel = class(TThread)
      private
        Fullfilename:string;
    //    ADOConnect:TADOConnection;
        ADOQuery1:TADOQuery;
        k:integer;
        procedure GetEditText;
        { Private declarations }
      protected
        procedure Execute; override;
      public
        Constructor Create(filename:string);
      end;implementationuses UMain,dialogs;{ Important: Methods and properties of objects in visual components can only be
      used in a method called using Synchronize, for example,      Synchronize(UpdateCaption);  and UpdateCaption could look like,    procedure ImportExcel.UpdateCaption;
        begin
          Form1.Caption := 'Updated in a thread';
        end; }{ ImportExcel }Constructor ImportExcel.Create(filename:string);
    begin
      Fullfilename:=filename;
      Inherited Create(False);
    end;procedure ImportExcel.GetEditText;
    begin
      k:=StrToInt(Main.Edit1.text);
    end;procedure ImportExcel.Execute;
    var
       excelid:variant;
       i:integer;
    begin
      { Place thread code here }
    excelid:=Createoleobject('Excel.Application'); //1、创建连接
    excelid.visible:=false;
    excelid.workbooks.open(Fullfilename); //2、指定文件
    Synchronize(GetEditText);
    //self.FreeOnTerminate:=True;   //使线程结束时,触发OnTerminate事件Try
     try
      ADOQuery1:=TADOQuery.Create(nil);
      with ADOQuery1 do
      begin
        ConnectionString:='Provider=MSDASQL.1;Persist Security Info=True;User ID=wujy;Data Source=mjgl';
        Close;
        SQL.Clear;
        SQL.Text:='select * from jgfy';
        Open;
      end;
    for i:=3 to 1000 do  //最大行数1000
    begin
        //判断是否结束
        if Trim(Excelid.WorkBooks[1].Worksheets[k].Cells[i,1].Value)<>'' then
        begin
          with ADOQuery1 do
          begin
            Append;
            FieldByName('rdate').Value:=Excelid.WorkBooks[1].Worksheets[k].Cells[i,1].Value;
            FieldByName('moldid').Value:=Excelid.WorkBooks[1].Worksheets[k].Cells[i,2].Value;
            FieldByName('gz').Value:=  Excelid.WorkBooks[1].Worksheets[k].Cells[i,3].Value;
            FieldByName('amount').Value:=  Excelid.WorkBooks[1].Worksheets[k].Cells[i,4].Value;
            FieldByName('fkfs').Value:=  Excelid.WorkBooks[1].Worksheets[k].Cells[i,5].Value;
            FieldByName('maker').Value:=  Excelid.WorkBooks[1].Worksheets[k].Cells[i,6].Value;
            FieldByName('jgs').Value:=  Excelid.WorkBooks[1].Worksheets[k].Cells[i,7].Value;
            FieldByName('memo').Value:=  Excelid.WorkBooks[1].Worksheets[k].Cells[i,8].Value;
            Post;
          end;
        end
          else break;
    end; //for
    except
      adoquery1.Free;
      excelid.quit;
      SendMessage(Main.Handle,UM_SUCCESS,1,0);
    //  showmessage('导入出错!');
    end;
    finally
      excelid.quit;
      ADOQuery1.Free;
      SendMessage(Main.Handle,UM_SUCCESS,0,0);
    //  showmessage('导入成功');
    end;
    end;end.
      

  13.   

    在 ImportExcel 类中增加一个 OnFinish 事件, 在 Execute 方法的末尾调用一下Synchronize(DoFinish);type
       TOnFinish = procedure(Sender: TObject; ASuccess: Boolean) of object;procedure ImportExcel.DoFinish()
    begin
       if Assigned(FOnFinish) then
          try
             FOnFinish(Self, FSuccess);
          except
          end;
    end;这里只是大概说一下,具体实现自己去概括。
      

  14.   

    procedure ImportExcel.DoFinish; 
    begin 
       if Assigned(FOnFinish) then
          try 
             FOnFinish(Self,   FSuccess); 
          except 
          end; 
    end; C++ 程序写多了,Delphi 语法都忘了