Vielen Dank nochmal für das Feedback.
Ich habe es jetzt hinbekommen,
als Service habe ich jetzt einen "Zwischen Threat" der immer einige Sekunden wartet bis die Funktion ein weiteres Mal ausgeführt wird, ohne dass die Runtime blockiert wird.
Die separaten Threads habe ich in eine separate Klasse gepackt, ob das zwingen nötig ist, habe ich jetzt nicht getestet. So klappt es auf jeden Fall 
Nur die Auslösung ist noch ein bisschen unschön, ich habe eine Zeitfunktion die eine Dummy Funktion auslöst, die eigentlich nichts macht, nur einen sinnlosen Sollwert toggelt.
Wäre schöner, ich könnte das direkt mit der Zeitfunktion antriggern...
Code:
using System;
using Scada.AddIn.Contracts;
using System.Threading;
using System.Collections.Generic;
using System.Windows.Forms;
namespace Export_Reports
{
///
/// Description of Project Service Extension.
///
[AddInExtension("Export Reports als Dienst", "Dieser Dienst führt gesteuert durch eine Zeitfunktion Exporte von Energie Reports durch", DefaultStartMode = DefaultStartupModes.Auto)]
public class ProjectServiceExtension : IProjectServiceExtension
{
#region IProjectServiceExtension implementation
Scada.AddIn.Contracts.IProject myProject;
public void Start(IProject context, IBehavior behavior)
{
//Errorhandling
try
{
//Deklaration
myProject = context;
//Anmelden des Event zur Überwachung der Dummyfunktion welche von der Zeitfunktion ausgelöst wird
myProject.FunctionCollection.FunctionExecuting += FunctionCollection_FunctionExecuting;
}
//Errorhandling
catch (Exception)
{
return;
}
}
public void FunctionCollection_FunctionExecuting(object sender, Scada.AddIn.Contracts.Function.FunctionExecutingEventArgs e)
{
//Errorhandling
try
{
//Deklaration
List Index = new List();
//Instandzieren der Klasse + übergabe Parameter an Constructor
ThreadContainer myThread = new ThreadContainer(Index, myProject);
//Wenn ausgeführte Funktion gesuchte Dummyfunktion ist, starte mit dem Export
if (e.Function.Name == "FU_ADDIN_Export_Report")
{
//###############################################################################################
//Liste der ZählerIndexe, welche exportiert werden sollen, weitere Zähler bitte hier eintragen...
//Druckluft Zähler #0
Index.Add("140");
//Strom Zähler #1
Index.Add("325");
//Strom Zähler #2
Index.Add("120");
//###############################################################################################
//Starte seperaten "zwischen" Thread der keinen Zugriff auf API hat
Thread Thread_1 = new Thread(myThread.Thread_1);
Thread_1.Start();
}
}
//Errorhandling
catch (Exception)
{
return;
}
}
public void Stop()
{
//Abmelden des Event zur Überwachung der Funktion
myProject.FunctionCollection.FunctionExecuting -= FunctionCollection_FunctionExecuting;
}
//Seperate Klasse für Sub Threads
public class ThreadContainer
{
//Deklaration
List m_Index;
IProject m_Project;
//Constructor (kann keinen Rückgabewert enthalten)
public ThreadContainer(List Index, IProject myProject)
{
m_Index = Index;
m_Project = myProject;
}
//zwischen Threat
//Dient zur Verzögerung zwischen den einzelnen Funktionsaufrufen
//Bis ein pdf erzeugt ist und die Funktion erneut verwedet werden kann,
//dauert es bis zu 3 Sekunden
public void Thread_1()
{
//Wichtig keine Aufrufe der API damit Thread ausßerhalb des Main Thread läuft und die Runtime nicht blockiert wird.
//Errorhandling
try
{
for (int i = 0; i <= m_Index.Count - 1; i++)
{
//Aufruf Thread zum Ändern und Ausführen der Reportfunktionen
Thread thread_2 = new Thread(Thread_2);
//Übergabe des jeweiligen Index an Thread_2
thread_2.Start(m_Index[i]);
//Verzögerung 5sek
Thread.Sleep(10000);
}
}
//Errorhandling
catch (Exception)
{
return;
}
}
public void Thread_2(Object ob)
{
//Errorhandling
try
{
//Deklaration
Scada.AddIn.Contracts.Function.IFunction obFctTrend;
int i = Convert.ToInt32((string) ob);
//RT Funktion welche bearbeitet wird (Wochenreport)
obFctTrend = m_Project.FunctionCollection["FU_Export_Report_Woche"];
//Ersetzen des Index der verknüpften Variablen in der Funktion auf den Index des aktuellen Zähler
obFctTrend.SetDynamicProperty("Filter[0].DataSet[0].Filter[0].VarInfo[0].Variable", m_Project.VariableCollection["Visu_UDINT_EnergieVerbrauch[" + i + "]"].Name);
obFctTrend.SetDynamicProperty("Filter[0].DataSet[0].Filter[0].VarInfo[0].VarName", m_Project.VariableCollection["Visu_UDINT_EnergieVerbrauch[" + i + "]"].Name);
obFctTrend.SetDynamicProperty("Filter[0].DataSet[1].Filter[0].VarInfo[0].Title", m_Project.VariableCollection["EnergyCounter[" + i + "].sFunctionName"].Name);
obFctTrend.SetDynamicProperty("Filter[0].DataSet[1].Filter[0].VarInfo[1].Title", m_Project.VariableCollection["EnergyCounter[" + i + "].sFunctionDescription"].Name);
obFctTrend.SetDynamicProperty("Filter[0].DataSet[2].Filter[0].VarInfo[0].Title", m_Project.VariableCollection["EnengyCounter[" + i + "].Monatswechsel"].Name);
obFctTrend.SetDynamicProperty("Filter[0].DataSet[2].Filter[0].VarInfo[1].Title", m_Project.VariableCollection["EnergyCounter[" + i + "].Vormonatswechsel"].Name);
obFctTrend.SetDynamicProperty("Filter[0].DataSet[3].Filter[0].VarInfo[0].Title", m_Project.VariableCollection["EnergyCounter[" + i + "].nType"].Name);
obFctTrend.SetDynamicProperty("Filter[0].DataSet[3].Filter[0].VarInfo[1].Title", m_Project.VariableCollection["EnergyCounter[" + i + "].nUnit"].Name);
obFctTrend.CreateDynamicProperty("Filter[0].Fct_Filename");
obFctTrend.SetDynamicProperty("Filter[0].Fct_Filename", "D:\\Export Runtime\\Export_" + i + "_Woche");
//Ausführen der geänderten RT Funktiuon
obFctTrend.Execute();
//Meldung in CEL schreiben
m_Project.ChronologicalEventList.AddEventEntry("Report für " + m_Project.VariableCollection["EnergyCounter[" + i + "].sFunctionName"].Name + " erzeugt");
}
//Errorhandling
catch (Exception err)
{
//Fehlermeldung in CEL schreiben
m_Project.ChronologicalEventList.AddEventEntry("Fehler in Thread 2 bei Export von Reports: " + err.Message);
}
}
}
#endregion
}
}