2014-10-01 3 views
0

У меня есть приложение с потоком для использования OPC. этот поток делает связь с OPC Factory Server и получает уведомление об автоматизации.Как хорошо общаться с OPC?

OPC: v 3.40.2808.0

языка сайта: Pascal, IDE: Delphi XE 2

связь с сервером хорошо и уведомление пришедшего. но время от времени, обслуживание не совсем и мое приложение не получает все уведомления.

Я не уверен, что этот вопрос пришел из моего кода, но для объяснения мало:

GestOPC = class(TThread) 
    contructor Create(suspendu:boolean); 
    destructor Destroy;override; 
    procedure C******; // Called by connexion 
    private 
     procedure Execute;override; 
     procedure CallGestOPCMainLabelAtt(const s : string);// IU Calling 
     procedure Call****; 
     procedure Call****; 
     procedure Call****; 
    public 
     sCallIHM :string; 
     ***: boolean; 
     ***: LongInt; 
     ThreadListNotif: TThreadList, 
     ServeurIF : OPCServer; 
     OPCDataCallBack:IOPCDataCallBack; 
     Buffer_notif : ^TNotif; 
     procedure connexion; 
    end; 

TOPCDataCallback = class (TInterfacedObject, IOPCDataCallback) 
public 
    function OnDataChange(.....)HResult;stdcall; 
    function OnReadComplete(.....)HResult;stdcall; 
    function OnWriteComplete(.....)HResult;stdcall; 
    function OnCancelComplete(.....)HResult;stdcall; 
end; 

OnDataChange ниток OPC в: Это событие для получения уведомления

function TOPCDataCallback.OnDataChange (dwTransid : DWORD; hgroup:OPCHANDLE; hrMasterquality: HResult; 
hrMastererror : HResult;dwCount : DWORD;phClientItems:POPCHANDLEARRAY;pvValues: POleVariantArray; 
pwQualities:PWordArray; pftTimeStamps : PFileTimeArray; pErrors :PResultList): HResult; 

var 
ClientItems :POPCHANDLEARRAY; 
Values: POleVariantArray; 
Qualities : PWordArray; 
i,iCountBadItem:integer; 

Begin 
    if not bClosing then ///It's to not do anything if the app is closing. 
    begin 
     //Initialisation 
     iCountBadItem := 0; //this is for count during debbugging all notification unreadable 
     Result := s_OK; 
     ClientItems := POPCHANDLEARRAY (phClientItems); 
     Values := POleVariantArray(pvValues); 
     for i := 0 to dwCount -1 do 
     begin 
      if Qualities[i] = OPC_QUALITY_GOOD then 
      begin 
       new(ClientOPC.Buffer_notif); 
       ClientOPC.Buffer_notif^.groupe_handle.indice_type1 := hGroup; 
       ClientOPC.Buffer_notif^.item_client := ClientItems[i]; 
       ClientOPC.Buffer_notif^.valeur_item := Value[i]; 
       ClientOPC.ThreadListNotif.Add(ClientOPC.Buffer_Notif); 
         //This list is used in another Thread with LockList for use the notification. 
      end 
      else 
       iCountBadItem := iCountBadItem+1; 
     end; 
     end; 

Моя процедура Execute от резьбы OPC нет, чтобы быть уверенным, что у меня хороший прием:

procedure GestOPC.Execute; 
begin 
    NameThreadForDebugging('GestOPC'); 
    while (not Terminated) do 
    begin 
     sleep(100); 
    end; 
end; 

Мой поток создается событие FormCreate моей основной формы с:

 ClientOPC := GestOPC.Create(false); 
    ClientOPC.FreeOnTerminate := false; 

И связь является запуск через А ButtonClick»Событие:

 ClientOPC.Connexion; 

Функция связь начал создавать приемник TOPCDataCallBack, сделать соединение с Ofs, сделать SQL-вызов в базе данных и завершить динамическую модификацию моего интерфейса (причина, по которой OPC находится в потоке, - это не заморозить мой интерфейс во время соединения).

Для моего IU Calling я использовать эту структуру:

sCallIHM := "Ceci est un exemple de mon travail ;) "; 
Queue( 
    procedure 
     begin 
     CallGestOPCMainLabelAtt(sCallIHM); 
     end) ; 

Как я могу обновить что быть Сюр, чтобы получить все мое сообщение?

Спасибо за чтение =)

ответ

4

Этот код полностью недоразумение как использовать TThread. Ваш метод Execute ничего не делает, поскольку касается дизайна приложения нет нитки. Все ваши функции GestOPC просто исполняются на любом потоке, который их вызывает. Поскольку вы используете Queue и documentation explicitly statesПредупреждение: не вызывайте очередь из основного потока., это очевидная ошибка.

Вызов Queue здесь не может быть ошибкой, конечно. Вы ничего нам не сообщили о своей библиотеке OPC и, конечно, Библиотеки OPC поднимают события в рабочем потоке. Если это так, вы избегаете ошибки на удачу - если это не так, тогда у вас есть ошибка по дизайну. Только вы можете прочитать библиотечную документацию, которая определяет, в чем дело.

Дизайн этого приложения не соответствует действительности.Предложите, что забыли сегодня о TThread, превратите свой TThread в обычный класс, избавитесь от бесполезного метода Execute, избавитесь от звонков на QueueSynchronize, если у вас есть), и посмотрите, что произойдет. Затем найдите некоторое время, чтобы узнать, как работает TThread, и как писать правильный многопоточный код - особенно если вы не знаете, что делаете, важно сначала начать работать с одним потоком, а затем работать с моделью потоковой передачи , Это помогает отделить ошибки, вызванные проблемами потоков и ошибками, вызванными самим кодом.

Кроме того, отсутствующие данные с OPC-сервера могут также поступать из временного сглаживания. OPC-сервер производит выборку вашего полевого устройства с некоторой частотой опроса, которая может варьироваться от системы к системе и от тега к тегу. Эта скорость опроса может быть порядка 10-100 мс или более. Если значение в полевом устройстве меняется быстрее, чем этот показатель, OPC-сервер может пропустить изменение, и многие клиенты, основанные на событиях, поэтому не будут уведомлять об изменениях. Поэтому важно, чтобы вы гарантировали бы, что быстро меняющиеся аппаратные состояния защелкиваются или ставятся в очередь, если вы обязательно должны их соблюдать. При отладке вы должны быть уверены, что это не источник уведомлений о пропущенных изменениях.

+0

Извините, что я нищий ^^ ' – Guillaume

+0

@Guillaume Не сожалею. Один из самых важных уроков при запуске - не пытаться делать слишком много сразу - иначе вы в конце концов утонете в проблемах, которые вы не понимаете. Начните с простого решения и сначала запустите его, затем добавьте сложность позже. –

+0

Извините, что я новичок ^^ 'Но «Не вызывайте очередь из основного потока», я не использую это в основном потоке, нет? Сначала это применимо, это многопоточное приложение, которое я должен обновить для передачи в MQTT Communication. Я не синхронизирую, чтобы не замораживать мой поток при модификации IU. Итак, если я хорошо понимаю, я беру свою связь и свою OPCDataCallBack и помещаю ее в свой основной поток? Моя проблема, если я делаю это вызовом SQL, слишком долгое и очень долгое замораживание моего пользовательского интерфейса. После создания этой темы, это действительно изменит замораживание, и это очень приятно. извините за мой английский .. (этот веб-сайт шутит с редактированием ^^) – Guillaume

 Смежные вопросы

  • Нет связанных вопросов^_^