我最近在一个系统中这样使用Interface:
   1、ICustomAddin 接口名称
   2、TCustomAddin 继承自TInterfaceObject,并实现了ICustomAddin接口
   3、在DLL中使用一个函数返回该接口
   4、主程序中会用动态调用DLL,取得接口后调用接口的方法进行工作,有下列几种使用情况:
      4.1、在一个过程中取得接口并赋值给局域变量,使用完后赋值为nil——释放。
      4.2、在一个线程中取得接口并赋值给线程属性变量,使用完后赋值为nil——释放。然后线程结束。主线程会使用该线程取得的接口进行操作(设置Addin终止标记)
现在的问题是:
   4.1能够正确执行,多次执行都没有问题!但是4.2执行到退出线程处理函数时发生错误( EAccessViolation),错误发生在_IntfClear调用中。注意,并不是退出Execute而是Execute中的一个方法,这个方法使用了接口。
   请教各位富翁帮助选找问题,多谢!
说明:
   在这个多线程系统中不存在线程安全和访问冲突问题,对这一点我有充分的信心!

解决方案 »

  1.   

    >>主线程会使用该线程取得的接口进行操作是否在线程结束时释放了获得的ICustomAddin?或者说线程FreeOnTerminated?
      

  2.   

    当然,在线程结束前释放接口!主线程使用接口是在线程运行期间释放接口之前进行的,这一点确认无疑!而且不是用接口,使用其它方式我已经完成了功能!但是最近由于同一个Addin需要在不同线程中使用,所以改变了结构,由Addin的输出函数将创建对象并返回接口,线程使用完后会释放(而且一定会释放),在释放它时也不会出错,只是退出函数时出错!我不知_IntfClear为什么会在退出函数时执行!
      

  3.   

    EAccessViolation通常都由这几种原因产生:
    1 对象被释放后但对象被继续引用
    2 对象未被创建便被引用
    3 指针未初始化再仔细检查一下代码,必要时加Assigned()检查指针是否合法
      

  4.   

    你是在哪儿类里面实现ICustomerInteface的。
    按照delphi的内存管理,如果你的一个类实现了某个接口,那么每调用一次接口中的方法,在接口内部其实实现了
    _AddRef
    IntefaceMethod
    _ReleaseRef
    一旦接口的引用计数为0,接口将自动释放,并不需要手工释放。
    假如你的接口是被你定义的线程实现,那么在线程终止的时候,其相应创建的接口也将被释放
      

  5.   

    我的系统结构是这样的:
      1、在DLL中的类里实现接口,利用一个输出函数创建对象并返回接口:GetAddinIntface:ICustomAddin。
      2、主线程有各线程队列创建、管理制定数目的线程进行工作,这些
    线程从任务队列中取得任务并调用DLL返回的接口进行处理,主线程会
    通过接口(DLL返回的)对Addin设置终止标记,以便中途终止任务的处理。
       ---Load DLL 
       Try
    1     AddinIntf{属性,有读些方法,防止访问冲突} := GetAddinIntf;
    2     try
    3       AddinIntf.ProcTask(Params);
    4     finally
    5       AddinIntf:=nil;退出引用
    6     end;
       finally
         ----UnLoad DLL
       end;
       说明主线程使用是通过手工操作的,且使用了Assigned(AddinIntf)。
    错误发生在过程退出时,我将Load/Uload DLL块内的代码移到一个过程内,
    然后在这里调用线的过程问题就解决了。
       5 是释放了接口的,我跟踪到System中看过了,关键是在函数尾时有什么原因
    导致的再次释放接口?因为在函数退出前我就Unload DLL 了,当然会有空地址操
    作了!
       虽然问题暂时解决了,但百思不得其解,毕竟不合逻辑!
      

  6.   

    我试过使用DLL输出过程来释放,问题依旧!
    而且我事用下面的方法调用也不会出错:
    function CheckAddin: Boolean;
    var
      lIntf        : ICustomAddin;
    begin
      --LoadLibrary(FileName);
      try
        lIntf := GetAddinIntf;取得接口
        try
            Result := Assigned(lIntf);
            if Result then
            begin
              lCode := StrToIntDef(lIntf.GetProperty('Code'), 0);
              lVersion := StrToIntDef(lIntf.GetProperty('Version'), 0);
            end;
        finally
          lIntf := nil;
        end;
      except
          Result := False;
      end;
      --FreeLibrary(DLLHandle)
    end;