Autor Beitrag
UGrohne
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Veteran
Beiträge: 5502
Erhaltene Danke: 220

Windows 8 , Server 2012
D7 Pro, VS.NET 2012 (C#)
BeitragVerfasst: Mo 23.07.07 13:04 
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:

ausblenden volle Höhe 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.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 20451
Erhaltene Danke: 2264

Win 10
C# (VS 2019)
BeitragVerfasst: Mo 23.07.07 14:59 
Kann es sein, dass es Probleme macht, wenn die EventArgs im fremdem Thread erzeugt werden?

_________________
Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
UGrohne Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Veteran
Beiträge: 5502
Erhaltene Danke: 220

Windows 8 , Server 2012
D7 Pro, VS.NET 2012 (C#)
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Veteran
Beiträge: 5502
Erhaltene Danke: 220

Windows 8 , Server 2012
D7 Pro, VS.NET 2012 (C#)
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Veteran
Beiträge: 5502
Erhaltene Danke: 220

Windows 8 , Server 2012
D7 Pro, VS.NET 2012 (C#)
BeitragVerfasst: 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 ...