# AGLink und die Verwaltung von Aufträgen



## raCotS (18 Juni 2008)

Hallo Leute!

Habe hier nen Versuchaufbau mit ner 315-2 PN/DP-CPU und programmiere mit C# die AGLink-Funktionen. So als kleinen Miniteil meiner Diplomarbeit, soll ich alle möglichen Funktionen von AGLink in C# verfügbar machen.

Leider hänge ich an der AGL_SetJobNotification fest, weil diese mir statt einer Benachrichtigungsinfo nur eine "System.AccessViolationException". Das kann wohl daran liegen, dass diese Methode nicht Asynchron aufgerufen wird. 
Die Struktur für NOTIFICATION existierte in der AGL4DotNET.cs noch nicht, also habe ich sie von Hand definiert:


```
[SIZE=2][[/SIZE][SIZE=2][COLOR=#2b91af][SIZE=2][COLOR=#2b91af]StructLayout[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2]([/SIZE][SIZE=2][COLOR=#2b91af][SIZE=2][COLOR=#2b91af]LayoutKind[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2].Sequential)][/SIZE]
[SIZE=2][COLOR=#0000ff][SIZE=2][COLOR=#0000ff]public [/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2][COLOR=#0000ff][SIZE=2][COLOR=#0000ff]struct[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2][COLOR=#2b91af][SIZE=2][COLOR=#2b91af]NOTIFICATION[/COLOR][/SIZE]
[/COLOR][/SIZE][SIZE=2]{ [/SIZE]
[SIZE=2][COLOR=#808080][SIZE=2][COLOR=#808080]///[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2][COLOR=#008000][SIZE=2][COLOR=#008000] Siehe Handbuch Seite 135 [/COLOR][/SIZE]
[/COLOR][/SIZE][SIZE=2][COLOR=#808080][SIZE=2][COLOR=#808080]///[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2][COLOR=#008000][SIZE=2][COLOR=#008000] Fensterhandle für Benachrichtigung über Message[/COLOR][/SIZE]
[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff][SIZE=2][COLOR=#0000ff]public [/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2][COLOR=#2b91af][SIZE=2][COLOR=#2b91af]HWND[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2] hwnd;[/SIZE]
[SIZE=2][COLOR=#808080][SIZE=2][COLOR=#808080]///[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2][COLOR=#008000][SIZE=2][COLOR=#008000] Nummer der Nachricht[/COLOR][/SIZE]
[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff][SIZE=2][COLOR=#0000ff]public [/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2][COLOR=#0000ff][SIZE=2][COLOR=#0000ff]uint[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2] WndMessage;[/SIZE]
[SIZE=2][COLOR=#808080][SIZE=2][COLOR=#808080]///[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2][COLOR=#008000][SIZE=2][COLOR=#008000] Falls Nachricht direkt an einen Thread geschickt werden soll[/COLOR][/SIZE]
[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff][SIZE=2][COLOR=#0000ff]public [/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2][COLOR=#2b91af][SIZE=2][COLOR=#2b91af]UInt32[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2] dwThreadID;[/SIZE]
[SIZE=2][COLOR=#808080][SIZE=2][COLOR=#808080]///[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2][COLOR=#008000][SIZE=2][COLOR=#008000] Gewünschte Nachricht für Thread[/COLOR][/SIZE]
[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff][SIZE=2][COLOR=#0000ff]public [/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2][COLOR=#0000ff][SIZE=2][COLOR=#0000ff]uint[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2] ThreadMessage;[/SIZE]
[SIZE=2][COLOR=#808080][SIZE=2][COLOR=#808080]///[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2][COLOR=#008000][SIZE=2][COLOR=#008000] Benachrichtung über Event[/COLOR][/SIZE]
[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff][SIZE=2][COLOR=#0000ff]public [/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2][COLOR=#2b91af][SIZE=2][COLOR=#2b91af]HANDLE[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2] hEvent;[/SIZE]
[SIZE=2][COLOR=#808080][SIZE=2][COLOR=#808080]///[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2][COLOR=#008000][SIZE=2][COLOR=#008000] Callback-Implementierung[/COLOR][/SIZE]
[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff][SIZE=2][COLOR=#0000ff]public [/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2][COLOR=#2b91af][SIZE=2][COLOR=#2b91af]IntPtr[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2] cb; [/SIZE][SIZE=2][COLOR=#008000][SIZE=2][COLOR=#008000]// oder public delegate void CB_Func();  :confused: [/COLOR][/SIZE]
[/COLOR][/SIZE][SIZE=2]} [/SIZE]
```
 


```
[SIZE=2][[/SIZE][SIZE=2][COLOR=#2b91af][SIZE=2][COLOR=#2b91af]DllImport[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2]([/SIZE][SIZE=2][COLOR=#a31515][SIZE=2][COLOR=#a31515]"AGLink40.dll"[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2])][/SIZE]
[SIZE=2][COLOR=#0000ff][SIZE=2][COLOR=#0000ff]private [/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2][COLOR=#0000ff][SIZE=2][COLOR=#0000ff]static [/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2][COLOR=#0000ff][SIZE=2][COLOR=#0000ff]extern [/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2][COLOR=#0000ff][SIZE=2][COLOR=#0000ff]unsafe [/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2][COLOR=#2b91af][SIZE=2][COLOR=#2b91af]Int32[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2] AGL_SetJobNotification([/SIZE][SIZE=2][COLOR=#2b91af][SIZE=2][COLOR=#2b91af]Int32[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2] JobNr, [/SIZE][SIZE=2][COLOR=#2b91af][SIZE=2][COLOR=#2b91af]NOTIFICATION[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2]* pN);[/SIZE]
[SIZE=2][COLOR=#0000ff][SIZE=2][COLOR=#0000ff]public [/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2][COLOR=#0000ff][SIZE=2][COLOR=#0000ff]static [/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2][COLOR=#0000ff][SIZE=2][COLOR=#0000ff]unsafe [/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2][COLOR=#2b91af][SIZE=2][COLOR=#2b91af]Int32[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2] SetJobNotification([/SIZE][SIZE=2][COLOR=#2b91af][SIZE=2][COLOR=#2b91af]Int32[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2] JobNr, [/SIZE][SIZE=2][COLOR=#0000ff][SIZE=2][COLOR=#0000ff]out [/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2][COLOR=#2b91af][SIZE=2][COLOR=#2b91af]NOTIFICATION[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2] pN )[/SIZE]
[SIZE=2]{ [/SIZE]
[SIZE=2][COLOR=#0000ff][SIZE=2][COLOR=#0000ff]int[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2] RetVal = AGL40_SUCCESS;;[/SIZE]
[SIZE=2][COLOR=#0000ff][SIZE=2][COLOR=#0000ff]fixed[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2] ([/SIZE][SIZE=2][COLOR=#2b91af][SIZE=2][COLOR=#2b91af]NOTIFICATION[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2]* notific = &pN)[/SIZE]
[SIZE=2]{[/SIZE]
[SIZE=2]RetVal = AGL_SetJobNotification(JobNr, notific);[/SIZE]
[SIZE=2]}[/SIZE]
[SIZE=2][COLOR=#0000ff][SIZE=2][COLOR=#0000ff]return[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2] (RetVal); [/SIZE]
[SIZE=2]}[/SIZE]
```
 
Und die Fkt. in der Form1.cs

```
[SIZE=2][COLOR=#0000ff][SIZE=2][COLOR=#0000ff]private[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2][COLOR=#0000ff][SIZE=2][COLOR=#0000ff]void[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2] DoSetJobNotification()[/SIZE]
[SIZE=2]{[/SIZE]
[SIZE=2][COLOR=#0000ff][SIZE=2][COLOR=#0000ff]int[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2] iRet;[/SIZE]
[SIZE=2][COLOR=#2b91af][SIZE=2][COLOR=#2b91af]AGL4[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2].[/SIZE][SIZE=2][COLOR=#2b91af][SIZE=2][COLOR=#2b91af]NOTIFICATION[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2] pN = [/SIZE][SIZE=2][COLOR=#0000ff][SIZE=2][COLOR=#0000ff]new[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2][COLOR=#2b91af][SIZE=2][COLOR=#2b91af]AGL4[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2].[/SIZE][SIZE=2][COLOR=#2b91af][SIZE=2][COLOR=#2b91af]NOTIFICATION[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2]();[/SIZE]
[SIZE=2]AddMessageLine([/SIZE][SIZE=2][COLOR=#a31515][SIZE=2][COLOR=#a31515]"Nummer des Auftrages: "[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2] + iJobNo.ToString());[/SIZE]
[SIZE=2]AddMessageLine([/SIZE][SIZE=2][COLOR=#a31515][SIZE=2][COLOR=#a31515]"ThreadID: "[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2] + pN.dwThreadID.ToString());[/SIZE]
[SIZE=2]AddMessageLine([/SIZE][SIZE=2][COLOR=#a31515][SIZE=2][COLOR=#a31515]"Event-Handle: "[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2] + pN.hEvent.ToString());[/SIZE]
[SIZE=2]AddMessageLine([/SIZE][SIZE=2][COLOR=#a31515][SIZE=2][COLOR=#a31515]"Window-Handle"[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2] + pN.hwnd.ToString());[/SIZE]
[SIZE=2]AddMessageLine([/SIZE][SIZE=2][COLOR=#a31515][SIZE=2][COLOR=#a31515]"ThreadMessage: "[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2] + pN.ThreadMessage.ToString());[/SIZE]
[SIZE=2]AddMessageLine([/SIZE][SIZE=2][COLOR=#a31515][SIZE=2][COLOR=#a31515]"WindowMessage: "[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2] + pN.WndMessage.ToString());[/SIZE]
 
[SIZE=2][COLOR=#0000ff][SIZE=2][COLOR=#0000ff]if[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2] ((iRet = [/SIZE][SIZE=2][COLOR=#2b91af][SIZE=2][COLOR=#2b91af]AGL4[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2].SetJobNotification(iJobNo, [/SIZE][SIZE=2][COLOR=#0000ff][SIZE=2][COLOR=#0000ff]out[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2] pN)) == [/SIZE][SIZE=2][COLOR=#2b91af][SIZE=2][COLOR=#2b91af]AGL4[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2].AGL40_SUCCESS)[/SIZE]
[SIZE=2]{[/SIZE]
[SIZE=2]}[/SIZE]
[SIZE=2]}[/SIZE]
```
 
Die Fkt. SetDevNotification und SetConnNotification sind entsprechend ähnlich aufgebaut. Diese liefern jedoch eh nur nullen, weil sicher der asynchrone Callback fehlt oder falsch programmiert ist. Da ich heute den ganzen Tag schon mit asynchronen Aufrufen und Delegaten herumgespielt habe und mir nicht im geringsten ein Lösungsansatz einfällt, bin ich schon langsam am verzweifeln. 
Googlen brachte mir in diesem Fall nicht den gewünschten Erfolg. 
Vielleicht hat jemand sowas ja mal für LibNoDave programmiert und kann mir dahingehend tips geben. Bin für jeden Hinweis/ Ratschlag etc. dankbar!

Grüße, Casi


----------



## Rainer Hönle (18 Juni 2008)

Ich gehe davon aus, dass es sich um AGLink 4.x handelt. Der .net-Wrapper ist nur synchron implementiert, da sonst der gc ein furchtbares Durcheinander anrichtet. Einfach mehrere Threads starten die für sich kommunizieren, oder einen Thread der kommuniziert und die Wünsche der anderen bearbeitet.


----------



## raCotS (18 Juni 2008)

Hallo Rainer!

Danke erstmal für die superschnelle Antwort!

Wie ist das gemeint?


> Einfach mehrere Threads starten die für sich kommunizieren, oder einen Thread der kommuniziert und die Wünsche der anderen bearbeitet.


 
Ist die Struktur okay so wie sie programmiert wurde und der DllImport auch?
Dann brauche ich im Form.cs also nur mehrere Threads zu starten bzw. ne Weile zu blockieren oder Thread.Sleeps() einzufügen, damit ne gewisse Zeit vergeht bis das Ergebnis Ausgabefertig ist? Nutze momentan noch Euer Standardform, um die Funktionen zum laufen zu bringen.

Gruß, Casi


----------



## Rainer Hönle (18 Juni 2008)

Jeder Auftrag an den .net-Wrapper wird synchron bearbeitet. Er kehrt also erst zurück, wenn dass Ergebnis vorliegt. Aus diesem Grund einfach in .net einige Threads anlegen die die notwendigen Werte lesen und schreiben. Wenn keine Parallelilät (= mehrere SPSen gleichzeitig) erforderlich ist, dann genügt auch ein Thread, der kommuniziert und von dem Hauptfenster die Aufträge bekommt und bearbeitet und das Ergebnis zurückgibt. Wenn es keine Rolle spielt, ob das Programm (wegen laufender Kommunikation) leicht verzögert reagiert, dann kann alles aus einem Thread (z.B. dem Hauptfenster aus) betrieben werden.
Was ist die genaue Anforderung und Aufgabenstellung? Warum soll asynchron kommuniziert werden?


----------



## raCotS (19 Juni 2008)

Hallo!
Also grundsätzlich soll ich alle verfügbaren Funktionen in AGL4DotNET bereitstellen, seien es Konvertierungen oder Diagnosen. 
Habe auch nur den einen Miniversuchsaufbau (mit o.g. SPS) zur Verfügung, wo nur OBs etc. vorhanden sind, ohne jegliche Komponenten. Also null Sensoren und Aktoren.

Auf die asynchrone Kommunikation bin ich nur gekommen, weil es so im Handbuch steht. Nicht nur weil "asynchron" drin steht, sondern weil mir die Prozessverarbeitung so logisch erscheint. Kann gut sein, dass ich falsch liege. Des Weiteren könnte es auch sein, dass die Methode SetJobNotification korrekt programmiert ist, nur null nutzen hat.


----------



## Rainer Hönle (19 Juni 2008)

Wenn Sie einen eigenen .net-Wrapper entwickeln und schreiben möchten, können Sie selbstverständlich alle Funktionen von AGLink, auch die asynchronen, implementieren. In dem in AGLink enthaltenen .net-Wrapper sind sämtliche Funktionen synchron implementiert. Die für die Asynchronität notwendigen Rückgabewerte werden Sie somit nie erhalten. Da bleibt dann nur selber implementieren. Die asynchronen Aufrufe wurden auf Grund der Komplikationen mit dem gc und dessen Eigenheiten beim Freigeben von Speicher wenn *ER* der Meinung ist, dass ein Speicher nicht mehr verwendet wird, nicht implementiert. Somit sind alle möglichen und verfügbaren AGLink-Funktionen in den Standard-.net-Wrapper enthalten. Was ist dann Ihre genaue Aufgabenstellung? 
Sollten Sie den Schritt zur Implementierung der asynchronen Funktionalität in einem eigenen .net-Wrapper gehen, erhalten Sie natürlich jede Unterstützung.


----------

