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