我在delphi 下用自动化接口编写opc 客户端软件。
引入了 OPC DAAutomation 2.0  OPCDAAuto.dlll
按照下面这个网页的方法,能采集到opc服务器的数据。
http://www.cnblogs.com/tekcat/archive/2010/07/06/1771792.html
但是,我想用在多线程方式下。
所有变量都放到多线程方式下生成,但是就是出错,
“应用程序调用一个已为另一线程整理的接口”。随便编程环境不同,但是方法是类似的,帮我问下啊。

解决方案 »

  1.   

    主线程调用如下:unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, OPCAutomation_TLB, OleServer, StdCtrls, ExtCtrls;type
      TForm1 = class(TForm)
        opcgrp1: TOPCGroup;
        opcgrps1: TOPCGroups;
        opcsrvr1: TOPCServer;
        btn1: TButton;
        btn2: TButton;
        btn3: TButton;
        edt1: TEdit;
        Timer1: TTimer;
        Button1: TButton;
        procedure btn1Click(Sender: TObject);
        procedure btn2Click(Sender: TObject);
        procedure btn3Click(Sender: TObject);
        procedure Timer1Timer(Sender: TObject);
        procedure Button1Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;var
      Form1: TForm1;
      Group:OPCGroup;
      testItem:OPCItem;
      OPCItems:string;
      OPCItemsValues:string;implementation{$R *.dfm}procedure TForm1.btn1Click(Sender: TObject);
    begin
      //连接OPC
      opcsrvr1.Connect1('S7200.OPCServer','');
      opcsrvr1.OPCGroups.DefaultGroupUpdateRate:=500;
      Group:=opcsrvr1.OPCGroups.Add('MyGroup');
      Group.IsActive:=True;
      testItem:=Group.OPCItems.AddItem('MicroWin.330282A00101.330282A001000101',0);
      //Group.OPCItems.AddItem('MicroWin.330282A00101.330282A001000101',1);
    end;procedure TForm1.btn2Click(Sender: TObject);
    begin
    //断开OPC
      opcsrvr1.OPCGroups.RemoveAll;
      opcsrvr1.Disconnect;
    end;procedure TForm1.btn3Click(Sender: TObject);
    var
      myvalue,myquality,mytimestamp:OleVariant;
      testItem1:OPCItem;
    begin
      //读OPC数据项
      testItem1:=Group.OPCItems.
      testItem1.Read(OPCDevice,myvalue,myquality,mytimestamp);
      edt1.Text:=myvalue;
    end;procedure TForm1.Button1Click(Sender: TObject);
    begin
      Timer1.Enabled:=True;
    end;procedure TForm1.Timer1Timer(Sender: TObject);
    var
      myvalue,myquality,mytimestamp:OleVariant;
    begin
      //读OPC数据项
      testItem.Read(OPCDevice,myvalue,myquality,mytimestamp);
      edt1.Text:=myvalue;
    end;
      

  2.   

    多线程调用如下
    unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, SyncObjs, ComObj, ActiveX,
      Dialogs, OPCAutomation_TLB, OleServer, StdCtrls, ExtCtrls;  type
        TthreadAcquire = class(Tthread)
        private
            OPCSrvr :TOPCServer;
            Group:TOPCGroup;
            testItem:OPCItem;
            strStyle: string;
        protected
            procedure  Execute;override;
        public
            constructor  Create(createsupped: Boolean; Style: String);
            destructor   Destroy; override;
      end;
    type
      TForm1 = class(TForm)
        opcsrvr1: TOPCServer;
        btn1: TButton;
        btn2: TButton;
        btn3: TButton;
        edt1: TEdit;
        procedure btn1Click(Sender: TObject);
        procedure btn3Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;var
      Form1: TForm1;
      Acquire_A: TthreadAcquire;
      CS: TRTLCriticalSection;
    implementation{$R *.dfm}
    {二、数据采集}
    constructor TthreadAcquire.Create(Createsupped: Boolean; Style :string);
    var
       i: integer;
    begin
        FreeOnTerminate:=False;
        strStyle:=Style;
        inherited Create(Createsupped);
        OPCSrvr:= TOPCServer.Create(nil);
        Group:= TOPCGroup.Create(nil);
        OPCSrvr.Connect1('S7200.OPCServer', '');
        OPCSrvr.OPCGroups.DefaultGroupIsActive:=True;
        OPCSrvr.OPCGroups.DefaultGroupUpdateRate:=500;
        Group.ConnectTo(OPCSrvr.OPCGroups.Add('MyGroup_'+strStyle));
        Group.IsActive:=True;
        Group.IsSubscribed:=False;
        Group.OPCItems.AddItem('MicroWin.330282A00101.330282A001000101',1);
    end;destructor TthreadAcquire.Destroy;
    begin
       opcsrvr.OPCGroups.RemoveAll;
       opcsrvr.Disconnect;
       Group.Free;
       opcsrvr.Free;
       inherited;
    end;procedure TthreadAcquire.Execute;
    var
      myValue,myQuality,myTimeStamp:OleVariant;
      tempValue:Real;
    begin
       inherited;
       CoInitialize(nil);
       while not  terminated do
       begin
          try
             //EnterCriticalSection(CS);
             testItem:=Group.OPCItems.Item(1);
             testItem.Read(OPCDevice,  myValue, myQuality, myTimeStamp);
             tempValue:=testItem.Value;
             Form1.edt1.Text:=IntToStr(3+Strtoint(Form1.edt1.Text));
             Application.ProcessMessages;
          finally
             //LeaveCriticalSection(CS);
          end;
          if not Self.Suspended Then Self.Suspend;
       end;
       CoUnInitialize;
    end;
    procedure TForm1.btn1Click(Sender: TObject);
    begin
      initializeCriticalSection(CS);
      if Acquire_A=nil then  begin Acquire_A:=TThreadAcquire.Create(True, 'A'); end;
    end;procedure TForm1.btn3Click(Sender: TObject);
    begin
           try
               if Acquire_A<>nil then  begin  if Acquire_A.Suspended then Acquire_A.Resume; end;
           except       end;
    end;
      

  3.   

    给你一段多线程的标准例子看看:
    unit uSendThread;interfaceuses
      Classes, SysUtils, Graphics, Forms;type
      TSendThread = class(TThread)
      private
        { Private declarations }
      protected
        procedure Execute; override;
      public
        constructor Create;
      end;implementationuses Main; {引用主窗体,注意下面的注释内容}{ 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 TSendThread.UpdateCaption;
        begin
          Form1.Caption := 'Updated in a thread';
        end; }{ TSendThread }constructor TSendThread.Create;
    begin
      inherited Create(False);
    end;procedure TSendThread.Execute;
    begin
      {这里面是你要获取数据的相关代码}
    end;end.{在主窗体中引用该线程单元}uses uSendThread;{主窗体中定义的线程变量}
    var  
      SendThread:TSendThread;{点击按钮或事件调用该线程:}SendThread:=TSendThread.create;