Hallo zusammen,
ich habe ein Problem mit einem EventWaitHandler, mit dem ich einfach nicht weiterkomme. Wie ich bereits in meinem anderen Thread erwähnt habe, sende ich mit einem Client eine Nachricht an einen Server, um von diesen eine Aufgabe abzufragen. Dabei läuft beim Client ein separater Thread zum empfangen der Antwort vom Server. Dieser Empfangsthread löst nun je nach empfangener Nachricht ein bestimmtes Event aus.
Nun gibt es den Fall, dass einem Ausgelösten Event z.B. eine Aufgabe abgefragt werden muss. Hier wollte ich nun die neuen Methoden einsetzen, damit das direkt ersichtlich wird.
Nun ist das Problem, dass wenn ich diese Funktion über ein ausgelöstes Event aufrufen will, er an der Stelle
Siehe:
Ich habe mir zum Test mal die Thread Ids der Funktionen ausgeben lassen. Das erste Console.WriteLine und Aufgabe aufgabe1 liefern an dieser Stelle die selbe Thread ID. Ist ja auch logisch. Das Zweite liefern dann die ID des Hauptthreads, da ja auch invoked wird.
Falls es noch relevant sein sollte, ist hier der Code des Empfangsthreads.
Das OnMessageReceived Ereignis sieht nun wie folgt aus:
Habt Ihr vielleicht einen Tipp, wie ich dieses Problem lösen kann?
Viele Grüße,
Marvin
ich habe ein Problem mit einem EventWaitHandler, mit dem ich einfach nicht weiterkomme. Wie ich bereits in meinem anderen Thread erwähnt habe, sende ich mit einem Client eine Nachricht an einen Server, um von diesen eine Aufgabe abzufragen. Dabei läuft beim Client ein separater Thread zum empfangen der Antwort vom Server. Dieser Empfangsthread löst nun je nach empfangener Nachricht ein bestimmtes Event aus.
Nun gibt es den Fall, dass einem Ausgelösten Event z.B. eine Aufgabe abgefragt werden muss. Hier wollte ich nun die neuen Methoden einsetzen, damit das direkt ersichtlich wird.
C#-Quellcode
- /// <summary>
- /// Ruft die Daten einer speziellen Aufgabe ab
- /// </summary>
- /// <param name="A_NR">Die ID der Aufgabe</param>
- /// <param name="istAktiveAufgabe">Ist die Aufgabe noch aktiv, oder wurde diese bereits erledigt?</param>
- /// <returns></returns>
- public Aufgabe GetAufgabe(long A_NR, bool istAktiveAufgabe = true)
- {
- if (!IsLoggedIn)
- throw new Exceptions.LoginRequiredException("Aktion erfordert Login am AufgabenServer. Bitte loggen Sie sich ein.");
- ServerProtokoll serverProtokoll = new ServerProtokoll()
- {
- RequestAufgabeNachricht = new RequestAufgabeNachricht(A_NR, istAktiveAufgabe)
- };
- Aufgabe result = null;
- AufgabenEventHandler handler = (object sender, AufgabeEventArgs e) =>
- {
- result = e.Aufgabe;
- ewh.Set();
- };
- GlobaleVariabeln.srv.AufgabenDataReceived += handler;
- serverProtokoll.Send();
- Console.WriteLine("Api ThreadID: {0}", Thread.CurrentThread.ManagedThreadId);
- if(result == null)
- ewh.WaitOne();
- GlobaleVariabeln.srv.AufgabenUpdated -= handler;
- return result;
- }
Nun ist das Problem, dass wenn ich diese Funktion über ein ausgelöstes Event aufrufen will, er an der Stelle
ewh.WaitOne();
dem Empfangsthread mit blockiert und ich dadurch nie eine Antwort erhalten kann.Siehe:
C#-Quellcode
- private void Srv_AufgabenViewReceived(object sender, AufgabenListeEventArgs e)
- {
- Console.WriteLine("Miau " + Thread.CurrentThread.ManagedThreadId);
- Aufgabe aufgabe1 = Hilfsklassen.AufgabenGlobals.aufgabenApi.GetAufgabe(14041);
- if (this.InvokeRequired)
- {
- this.Invoke(new MethodInvoker(delegate ()
- {
- FillDataGridView(e.Aufgaben);
- Console.WriteLine("TEST " + Thread.CurrentThread.ManagedThreadId);
- Aufgabe aufgabe = Hilfsklassen.AufgabenGlobals.aufgabenApi.GetAufgabe(14041);
- }));
- }
- else
- {
- FillDataGridView(e.Aufgaben);
- }
- }
Ich habe mir zum Test mal die Thread Ids der Funktionen ausgeben lassen. Das erste Console.WriteLine und Aufgabe aufgabe1 liefern an dieser Stelle die selbe Thread ID. Ist ja auch logisch. Das Zweite liefern dann die ID des Hauptthreads, da ja auch invoked wird.
Falls es noch relevant sein sollte, ist hier der Code des Empfangsthreads.
C#-Quellcode
- /// <summary>
- /// Empfängt alle Nachrichtenobjecte vom AufgabenServer
- /// </summary>
- private void Empfange()
- {
- List<byte> bytesReceived = new List<byte>();
- Console.WriteLine("Empfangs ThreadID: {0}", Thread.CurrentThread.ManagedThreadId);
- stop = false;
- while (IsConnected && !stop)
- {
- try
- {
- // Stream zum lesen holen
- while (connection.Available > 0 && connection.Connected)
- {
- isReceivingData = true;
- int size = (connection.Available > Int32.MaxValue) ? Int32.MaxValue : connection.Available;
- byte[] nextByte = new byte[size];
- connection.Receive(nextByte, 0, size, SocketFlags.None);
- bytesReceived.AddRange(nextByte);
- }
- isReceivingData = false;
- Thread.Sleep(100); // Nach jedem Durchgang warten wir 100ms, damit die CPU Auslastung nicht durchs permanente Abfragen bis auf 100% ansteigt!
- }
- catch (Exception ex)
- {
- Console.WriteLine(ex.Message);
- File.AppendAllText(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "error.log"), ex.Message + Environment.NewLine);
- bytesReceived.Clear();
- // Setze das Schleifen-Flag zurück
- // wenn ein Fehler in der Kommunikation aufgetreten ist
- // stop = true;
- }
- // Prüfen ob eine Nachricht vollständig angekommen ist
- if (bytesReceived.Contains(delimiter))
- {
- // Wir müssen an dieser Stelle prüfen ob wir mehr als eine Nachricht vollständig empfangen haben.
- int delimiterPos = bytesReceived.IndexOf(delimiter);
- byte[] data = bytesReceived.GetRange(0, delimiterPos).ToArray();
- bytesReceived.RemoveRange(0, delimiterPos + 1);
- OnMessageReceived(data);
- }
- if (bytesReceived.Count == 0)
- {
- bytesReceived = new List<byte>();
- GC.Collect();
- GC.WaitForPendingFinalizers();
- }
- }
- // Schließe die Verbindung zum Server
- if (!stop) // Wenn Stop = false, dann haben wir die Verbindung unabsichtlich verloren!
- Disconnect();
- }
Das OnMessageReceived Ereignis sieht nun wie folgt aus:
C#-Quellcode
- #region Nachricht erhalten
- /// <summary>
- /// Das Event wird getriggert, wenn wir eine Nachricht vollständig empfangen haben
- /// </summary>
- /// <param name="Data"></param>
- protected virtual void OnMessageReceived(byte[] Data)
- {
- isReceivingData = false;
- string data = Encoding.UTF8.GetString(Data);
- if (!string.IsNullOrWhiteSpace(data))
- {
- object nachricht = NachrichtenSerializer.DeserializeObject(data);
- if (nachricht.GetType() == typeof(ServerProtokoll))
- {
- // Caste nachricht zu ServerProtokoll
- ServerProtokoll serverProtokoll = nachricht as ServerProtokoll;
- // Prüfe Inhalt der Nachricht
- if (serverProtokoll.KonfigurationsNachricht != null)
- {
- GlobaleVariabeln.IsConfigured = serverProtokoll.KonfigurationsNachricht.IsConfigured;
- OnKonfigurationStatusReceived(new EventArgs());
- }
- if (serverProtokoll.LoginStatusNachricht != null)
- {
- if (serverProtokoll.LoginStatusNachricht.InvalidServerProtokoll)
- {
- OnInvalidProtokollDetected(new MessageEventArgs("Die Verbindung zum AufgabenServer wurde abgebrochen, da der Client eine neuere Protokollversion verwendet.", "Bitte führen Sie ein Update des AufgabenServers durch!"));
- }
- else if (serverProtokoll.LoginStatusNachricht.InvalidClientProtokoll)
- {
- OnInvalidProtokollDetected(new MessageEventArgs("Die Verbindung zum AufgabenServer wurde abgebrochen, da der Server eine neuere Protokollversion verwendet.", "Bitte führen Sie ein Update des Clienten durch!"));
- }
- IsLoggedIn = serverProtokoll.LoginStatusNachricht.LoginErfolgreich;
- LizenzenVerbraucht = serverProtokoll.LoginStatusNachricht.LizenzenVerbraucht;
- dieserMitarbeiter = serverProtokoll.LoginStatusNachricht.VerwaltungsNachricht.DieserMitarbeiter;
- GlobaleVariabeln.Arbeitsgruppen = serverProtokoll.LoginStatusNachricht.VerwaltungsNachricht.Arbeitsgruppen;
- GlobaleVariabeln.Mitarbeiter = serverProtokoll.LoginStatusNachricht.VerwaltungsNachricht.Mitarbeiter;
- GlobaleVariabeln.Mitarbeiterliste = serverProtokoll.LoginStatusNachricht.VerwaltungsNachricht.Mitarbeiterliste;
- GlobaleVariabeln.MitarbeiterlisteAlle = serverProtokoll.LoginStatusNachricht.VerwaltungsNachricht.MitarbeiterlisteAlle;
- GlobaleVariabeln.SmtpHost = serverProtokoll.LoginStatusNachricht.VerwaltungsNachricht.SmtpHost;
- GlobaleVariabeln.SmtpUser = serverProtokoll.LoginStatusNachricht.VerwaltungsNachricht.SmtpUser;
- GlobaleVariabeln.SmtpPasswort = serverProtokoll.LoginStatusNachricht.VerwaltungsNachricht.SmtpPasswort;
- GlobaleVariabeln.SmtpPort = serverProtokoll.LoginStatusNachricht.VerwaltungsNachricht.SmtpPort;
- GlobaleVariabeln.SmtpUseSsl = serverProtokoll.LoginStatusNachricht.VerwaltungsNachricht.SmtpUseSsl;
- GlobaleVariabeln.SmtpAbsendeEmail = serverProtokoll.LoginStatusNachricht.VerwaltungsNachricht.SmtpAbsendeEmail;
- GlobaleVariabeln.SmtpAbsendeName = serverProtokoll.LoginStatusNachricht.VerwaltungsNachricht.SmtpAbsendeName;
- GlobaleVariabeln.MailVerfahren = serverProtokoll.LoginStatusNachricht.VerwaltungsNachricht.MailVerfahren;
- GlobaleVariabeln.DynDnsUrl = serverProtokoll.LoginStatusNachricht.VerwaltungsNachricht.DynDnsUrl;
- GlobaleVariabeln.Anzeigelimit = serverProtokoll.LoginStatusNachricht.VerwaltungsNachricht.Anzeigelimit;
- GlobaleVariabeln.DruckEnabled = serverProtokoll.LoginStatusNachricht.VerwaltungsNachricht.DruckEnabled;
- GlobaleVariabeln.LizenzenAktiv = serverProtokoll.LoginStatusNachricht.VerwaltungsNachricht.LizenzenAktiv;
- GlobaleVariabeln.ClientsLizenzsiert = serverProtokoll.LoginStatusNachricht.VerwaltungsNachricht.ClientsLizenzsiert;
- GlobaleVariabeln.Arbeitsgruppen = serverProtokoll.LoginStatusNachricht.VerwaltungsNachricht.Arbeitsgruppen;
- GlobaleVariabeln.Arbeitsgruppen = serverProtokoll.LoginStatusNachricht.VerwaltungsNachricht.Arbeitsgruppen;
- OnLoginStatusRecieved(new LoginEventArgs(serverProtokoll.LoginStatusNachricht.LoginErfolgreich, serverProtokoll.LoginStatusNachricht.InvalidServerProtokoll, serverProtokoll.LoginStatusNachricht.InvalidClientProtokoll));
- }
- else if (serverProtokoll.AufgabenNachricht != null) // Uns erreicht eine Benachrichtigung zu einer Aufgabe
- {
- OnAufgabenUpdated(new AufgabeEventArgs(serverProtokoll.AufgabenNachricht.Aufgabe, serverProtokoll.AufgabenNachricht.NachrichtenTyp));
- }
- else if (serverProtokoll.BearbeitenStatusNachricht != null)
- {
- OnBearbeitenStatusReceived(new BearbeitenEventArgs(
- serverProtokoll.BearbeitenStatusNachricht.Aufgabe,
- serverProtokoll.BearbeitenStatusNachricht.DarfBearbeiten,
- serverProtokoll.BearbeitenStatusNachricht.AnfrageAktion,
- serverProtokoll.BearbeitenStatusNachricht.WirdBearbeitetVonUserId
- ));
- }
- else if (serverProtokoll.LoginNachricht != null) // Uns erreicht eine Loginanfrage am Server
- {
- // Den Typen gibt es zwar, allerdings wird dieser ausschließlich vom Server empfangen!
- }
- else if (serverProtokoll.ServerNachricht != null) // Uns erreicht eine spezielle Nachricht des Servers
- {
- // Muss in extra Thread ausgelagert werden, da ansonsten keine weiteren Nachrichten empfangen werden können!
- OnServerNachrichtReceived(new MessageEventArgs(serverProtokoll.ServerNachricht.Nachricht, serverProtokoll.ServerNachricht.Title));
- }
- else if (serverProtokoll.ChatNachricht != null) // Uns erreicht eine Chatnachricht
- {
- OnChatNachrichtReceived(new ChatEventArgs(serverProtokoll.ChatNachricht.AbsenderId, serverProtokoll.ChatNachricht.EmpfängerId, serverProtokoll.ChatNachricht.AbsenderName, serverProtokoll.ChatNachricht.EmpfängerName, serverProtokoll.ChatNachricht.Nachricht));
- }
- else if (serverProtokoll.KarusselAnfrageNachricht != null)
- {
- OnKarusselAnfrage(new KarusselEventArgs(serverProtokoll.KarusselAnfrageNachricht.Aufgabe));
- }
- else if (serverProtokoll.VerwaltungsNachricht != null)
- {
- GlobaleVariabeln.Arbeitsgruppen = serverProtokoll.VerwaltungsNachricht.Arbeitsgruppen;
- GlobaleVariabeln.Mitarbeiter = serverProtokoll.VerwaltungsNachricht.Mitarbeiter;
- GlobaleVariabeln.Mitarbeiterliste = serverProtokoll.VerwaltungsNachricht.Mitarbeiterliste;
- GlobaleVariabeln.MitarbeiterlisteAlle = serverProtokoll.VerwaltungsNachricht.MitarbeiterlisteAlle;
- GlobaleVariabeln.VerbundeneUser = serverProtokoll.VerwaltungsNachricht.VerbundeneUser;
- this.dieserMitarbeiter = serverProtokoll.VerwaltungsNachricht.DieserMitarbeiter;
- // Einstellungen
- GlobaleVariabeln.SmtpHost = serverProtokoll.VerwaltungsNachricht.SmtpHost;
- GlobaleVariabeln.SmtpUser = serverProtokoll.VerwaltungsNachricht.SmtpUser;
- GlobaleVariabeln.SmtpPasswort = serverProtokoll.VerwaltungsNachricht.SmtpPasswort;
- GlobaleVariabeln.SmtpPort = serverProtokoll.VerwaltungsNachricht.SmtpPort;
- GlobaleVariabeln.SmtpUseSsl = serverProtokoll.VerwaltungsNachricht.SmtpUseSsl;
- GlobaleVariabeln.SmtpAbsendeEmail = serverProtokoll.VerwaltungsNachricht.SmtpAbsendeEmail;
- GlobaleVariabeln.SmtpAbsendeName = serverProtokoll.VerwaltungsNachricht.SmtpAbsendeName;
- GlobaleVariabeln.MailVerfahren = serverProtokoll.VerwaltungsNachricht.MailVerfahren;
- GlobaleVariabeln.Anzeigelimit = serverProtokoll.VerwaltungsNachricht.Anzeigelimit;
- // Lizensierung
- GlobaleVariabeln.LizenzenAktiv = serverProtokoll.VerwaltungsNachricht.LizenzenAktiv;
- GlobaleVariabeln.ClientsLizenzsiert = serverProtokoll.VerwaltungsNachricht.ClientsLizenzsiert;
- GlobaleVariabeln.DruckEnabled = serverProtokoll.VerwaltungsNachricht.DruckEnabled;
- OnVerwaltungsUpdate(new EventArgs());
- }
- else if (serverProtokoll.SendAufgabenNachricht != null)
- {
- OnAufgabenViewReceived(new AufgabenListeEventArgs(serverProtokoll.SendAufgabenNachricht.Aufgaben));
- }
- else if (serverProtokoll.RequestVergesseneAufgabenNachricht != null)
- {
- OnVergesseneAufgabenReceived(new VergesseneAufgabenEventArgs(serverProtokoll.RequestVergesseneAufgabenNachricht.AndereUserVergessen, serverProtokoll.RequestVergesseneAufgabenNachricht.RestAufgabenTab, serverProtokoll.RequestVergesseneAufgabenNachricht.VergesseneGruppenAufgaben, serverProtokoll.RequestVergesseneAufgabenNachricht.ShowForms));
- }
- else if (serverProtokoll.RequestAufgabeAntwortNachricht != null)
- {
- OnAufgabenDataReceived(new AufgabeEventArgs(serverProtokoll.RequestAufgabeAntwortNachricht.Aufgabe, NachrichtenTypen.AufgabeAktion.Anfragen));
- }
- else if (serverProtokoll.FiveStarWarningNachricht != null)
- {
- OnFiveStarWarningReceived(new EventArgs());
- }
- else if (serverProtokoll.RequestAntwortGruppenAufgabenNachricht != null)
- {
- OnGruppenAufgabenReceived(new GruppeLöschenEventArgs(serverProtokoll.RequestAntwortGruppenAufgabenNachricht.Gruppe, serverProtokoll.RequestAntwortGruppenAufgabenNachricht.Aufgaben));
- }
- else if (serverProtokoll.RequestMitarbeiterPunkteNachricht != null)
- {
- OnPunkteDataReceived(new PunkteEventArgs(serverProtokoll.RequestMitarbeiterPunkteNachricht.PunkteZeitraum, serverProtokoll.RequestMitarbeiterPunkteNachricht.PunkteGesamt, serverProtokoll.RequestMitarbeiterPunkteNachricht.AnzahlAufgabenVergütet, serverProtokoll.RequestMitarbeiterPunkteNachricht.PunkteVerlauf));
- }
- else if (serverProtokoll.RequestMitarbeiterAuslastungNachricht != null)
- {
- OnAuslastungsDataReceived(new AuslastungEventArgs(serverProtokoll.RequestMitarbeiterAuslastungNachricht.AufgabenZuerledigen));
- }
- else if(serverProtokoll.ErrorNachricht != null)
- {
- //TODO: Event auslösen
- }
- else if(serverProtokoll.StatusNachricht != null)
- {
- OnStatusReceived(new StatusEventArgs(
- serverProtokoll.StatusNachricht.Message,
- serverProtokoll.StatusNachricht.Status));
- }
- else
- {
- // Es handelt sich zwar um ein übermitteltes Serverprotokoll, allerdings haben wir bis hier hin keinen Inhalt gefunden
- // Das bedeutet, dass uns ein Nachrichtentyp einer nicht unterstützen Revision erreicht hat!
- }
- serverProtokoll.Dispose();
- }
- else
- {
- // Uns erreicht ein unbekanntes Flugobject!
- }
- }
- }
Habt Ihr vielleicht einen Tipp, wie ich dieses Problem lösen kann?
Viele Grüße,
Marvin