Entwickler-Ecke

Basistechnologien - Invoke aus Timer-Event


UGrohne - Mo 23.07.07 13:04
Titel: Invoke aus Timer-Event
Hallo,

ich hoffe, ich hab die Sache mit dem Invoke nun verstanden, daher mal eine Frage:

Ich habe eine Klasse, welche einen Timer beinhaltet. Dieser ruft eine Methode auf, die wiederum ein Event auslösen soll, das von der Hauptanwendung abgefangen wird, um eine ListBox zu befüllen.

Problem ist nun, dass ich dem Anwender der Klasse eigentlich nicht zumuten möchte, mit delegates und invoke zu arbeiten, sondern er soll direkt aus dem EventHandler heraus, GUI-Komponenten befüllen können. Aber irgendwie bekomme ich das nicht hin.

Folgendermaßen sieht mein Aufbau aus:


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
    public class NewMailEventArgs : EventArgs
    {
        List<string> messageIds;
        public NewMailEventArgs(List<string> messageIds)
        {
            this.messageIds = messageIds;
        }
        public List<string> MessageIds
        {
            get 
            {
                return messageIds;
            }
            set
            {
                messageIds = value;
            }
        }
    }

//
// Anwender-Klasse
//
    public class ExchangeCommunication
    {        
        //Events
        public delegate void NewMailEventHandler(object sender, NewMailEventArgs e);
        public event NewMailEventHandler OnNewMailHandler;
        protected void OnNewMail(object sender, NewMailEventArgs e)
        {
            if (OnNewMailHandler != null)
                OnNewMailHandler(sender,e);
        }

        void PullEvents(object sender, ElapsedEventArgs e)
        {
            // [....]
            //Call event
            if (messageIds.Count>0)
            {
                NewMailEventArgs newMailEventArgs = new NewMailEventArgs(messageIds);
                object[] objs = new object[2];
                objs[0] = this;
                objs[1] = newMailEventArgs;
                syncInvoke.Invoke(new NewMailEventHandler(OnNewMail), objs);
            }
        }
    }

PullEvents wird von meinem Timer ausgelöst und löst dann den Event aus. Mit meinem Synchronizer funktioniert das so aber nicht, ich bekomme in der Hauptanwendung immer noch Fehler bezüglich threadübergreifender Zugriffe.

Wie kann ich dieses Problem umgehen/lösen?


Christian S. - Mo 23.07.07 14:59

Kann es sein, dass es Probleme macht, wenn die EventArgs im fremdem Thread erzeugt werden?


UGrohne - Mo 23.07.07 15:11

user profile iconChristian S. hat folgendes geschrieben:
Kann es sein, dass es Probleme macht, wenn die EventArgs im fremdem Thread erzeugt werden?

Gute Frage, müsste ich bei Gelegenheit testen. Hab nur gerade schon meine Virtuelle Maschine heruntergefahren und arbeite an wichtigeren Sachen *g*.

Aber wenn die EventArgs das Problem versursachen, würde es dann überhaupt etwas bringen, wenn ich stattdessen nur die List<string> als Parameter verwende? Diese muss ich ja an derselben Stelle erzeugen bzw. übergeben.


UGrohne - Do 26.07.07 08:53

Also das funktioniert auch nicht. Ich habe jetzt direkt messageIds als Parameter übergeben lassen und diese im Konstruktor der gesamten Klasse aufrufen lassen, also außerhalb des Timers.

Aber ich bekomme immer noch, auch über das Invoke, die Thread-Exception :(


UGrohne - Do 26.07.07 10:39

Folgendes hat nun funktioniert: Wenn ich ein Control des die Klasse erzeugenden Forms übergebe und von diesem das Invoke verwende, funktioniert es. Ich wollte aber eigentlich vermeiden, dass der Verwender der Klasse unbedingt ein Controls-Element übergeben muss, da es sich ja auch um eine Konsolenanwendung handeln kann.

Und eigentlich wollte ich auch vermeiden, dass der Anwender ein extra Objekt erstellen muss, dass er mir dann übergibt. Ich habe ja eine Synchronizer-Klasse, die von Controls unabhängig ist, diese erzeuge ich im Konstruktor meiner Klasse. Nur dummerweise scheint sie dort dann nicht zu funktionieren ...