ich nutze die API eines Displayherstellers um ein USB-LCD Display anzusprechen. Im GUI-Thread (in meiner Form) erzeuge ich ein Objekt der Diplayklasse und registriere einen EventHandler. Der Eventhandler wird aufgerufen wenn die API eine Logmeldung auszugeben hat. Diese Logmeldung schreibe ich dann im EventHandler in eine ListBox auf meiner Form. Das funktioniert auch alles super solange ich die ganze Logik des Displays im GUI-Thread erledige. Da dies aber aus diversen Gründen nicht geht habe ich die ganze Funktionalität in einen separaten Thread ausgelagert.
Das Objekt der Diplayklasse übergebe ich in meiner Form an den Konstruktor einer von BackgroundWorker abgeleiteten Klasse die die ganze Arbeit mit dem Display in einem seperaten Thread erledigt.
Sobald nun der Log-Eventhandler aufgerufen wird (der ja im GUI Thread registriert ist) kommt es zum "ungültigen Threadübergreifenden Vorgang". Das aber nicht immer! Nur in dem Falle wenn im BackgroundWorker ein anderes Event der API ausgelöst wird (ScrollFinished Event - Wenn das Display einen kompletten Text-Scrolldurchgang erledigt hat). Ich erkenne keinen direkten Zusammenhang warum dieses Event etwas direkt mit dem Log zu tun haben sollte (denn alle anderen Logmeldungen die nicht durch das ScrollFinished Event im BackgroundWorker ausgelöst werden kommen ja durch).
Dafür habe ich noch keine geeignete Lösung gefunden. Der Sachverhalt ist nicht ganz einfach, ich hoffe ich konnte es halbwegs verständlich rüberbringen. Hier ein paar Code-Snippets:
GUI Klasse:
private iMonWrapperApi imon; //Das ist die API
private DisplayHandler displayHandler; //Das ist die von BackgroundWorker abgeleitete Klasse die die Logik enthält
this.imon = new iMonWrapperApi();
this.imon.Log += wrapperApi_Log; //Registrierung des Eventhandlers im GUI Thread
this.imon.StateChanged += wrapperApi_StateChanged; //Wenn z.b. ein Diplay vom USB angeschlossen oder abgezogen wird wird dieses Ereignis aufgerufen
this.displayHandler = new DisplayHandler(this.imon); //Übergabe des API Objekts an den BackgroundWorker
this.displayHandler.RunWorkerAsync(); //Starte den Backgroundworker
private void wrapperApi_Log(object sender, iMonLogEventArgs e)
{
listBoxLog.Items.Add(e.message);
}
BackGroundWorker Klasse:
class DisplayHandler : BackgroundWorker
{
public DisplayHandler(iMonWrapperApi imon)
{
.....
this.imon.StateChanged += stateChanged;
}
protected override void OnDoWork(DoWorkEventArgs e)
{
//Hier wird die Arbeit verrichtet
}
private void stateChanged(object sender, iMonStateChangedEventArgs e)
{
//Falls ein LCD Display angeschlossen wurde unterstützt es die Scrollfunktion und der passende EventHandler muss registriert werden. Bei anderen Displaytypen wird dieser Eventhandler wieder getrennt!
if (diplayType == iMonDisplayType.LCD)
this.imon.LCD.ScrollFinished += lcdScrollFinished;
else
this.imon.LCD.ScrollFinished -= lcdScrollFinished;
}
private void lcdScrollFinished(object sender, EventArgs e)
{
Thread.Sleep(1000); //Warte eine Sekunde
this.update(); //Beginne Text von Vorne aufs LCD zu schreiben
}
}
Ich hoffe Ihr habt ein paar Tips für mich.
Viele Grüße Viper