Autor Beitrag
Raorkon
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 86
Erhaltene Danke: 1



BeitragVerfasst: Fr 24.06.11 12:24 
Hallo Zusammen,

ich habe ein seltsames Problem:

ich habe eine Form die eine Hardware initalisiert und das dabei auch Werte über ein Event zurückgibt:
ausblenden C#-Quelltext
1:
2:
3:
//Form 1
            EventHandler evt = new EventHandler(this.BarcodeReader_OnRead);
            SingletonProvider<Symbol_Class>.Instance.AttachReadNotify(evt);


soweit so gut, funktioniert auch tadellos

nun wird aus dieser Form ein Menü aufgerufen


ausblenden C#-Quelltext
1:
2:
3:
4:
5:
//form 1
            MainForm mainForm = new MainForm();
            BarcodeReaderDeregisterMethods(); // events löschen
            mainForm.ShowDialog();
//danach werden die Events wieder neu zugewiesen


nun rufe ich aus dem Menü heraus eine weitere Form auf

ausblenden C#-Quelltext
1:
2:
3:
//2.Form ohne Events
            Form blub= new Form();
            blub.ShowDialog();




in der Form weise ich ebenfalls wieder events zu
ausblenden C#-Quelltext
1:
2:
3:
//3.Form wieder mit Events
            EventHandler evt = new EventHandler(this.BarcodeReader_OnRead);
            SingletonProvider<Symbol_Class>.Instance.AttachReadNotify(evt);


und da habe ich mein Problem:

denn sobald das Event in der blub Form ausgeführt werden soll, passiert gar nichts.
D.h. mein zugewiesenes Event wird nicht beachtet bzw. die Methode wird nicht angesprochen.

Sobald ich wieder die 3. und 2. Form schliesse, wird mein Event (aus Form 3) ausgeführt in der Methode der 1.Form.

was ich schon rausgefunden habe ist folgendes:

Sobald ich die Form 1 dispose funktioniert auch das Event aus Form 3.

Nur ist das keine Alternative für mich da ich in der 1.Form unter anderem den Singleton intialisiere und auch noch einige andere wichtige Programmparameter setze. Ausserdem will ich der Ursache auf den Grund gehen.


ich hoffe ich habe mich halbwegs verständlich ausgedrückt.

Thx für eure Hinweise
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4805
Erhaltene Danke: 1061

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Fr 24.06.11 15:59 
Hallo Raorkon,

ein wenig schwierig, dir eine konkrete Antwort zu geben, da dies verschiedene Ursachen haben könnte.
Als erstes tippe ich mal auf ShowDialog (bzw. das zweifache Aufrufen davon). Ändere mal testweise dies in einen einfachen Show()-Aufruf um.

In welcher Methode führst du denn den ShowDialog()-Aufruf durch, im Konstruktor oder in der Form.Load()-Ereignismethode?

Und dann ist nicht klar, was genau die SingletonProvider<Symbol_Class>.Instance.AttachReadNotify()-Methode macht. Registriert diese nur den Event? Und welche Klasseninstanz führt dann konkret diese Events aus?

Außerdem habe ich noch meinen eigenen Artikel zur Kommunikation von 2 Forms, der dir evtl. weiterhelfen könnte...
Raorkon Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 86
Erhaltene Danke: 1



BeitragVerfasst: Fr 24.06.11 18:18 
Hallo TH69,

in der ersten Form initalisiere ich den Barcodescanner z.B. dort wird festgelegt welchen Barcode gescannt werden soll.
Ausserdem wird in der ersten Form die Möglichkeit geben, das man sich Tasteneingabe oder per Scanner eines Barcodes anmelden kann.

das mach ich alles im Load-Event der Form1


In der 2.Form soll nicht gescannt werden, d.h. dort wird dem Scanner auch keinem Event zugeordnet


in der 3.Form soll wieder gescannt werden, dafür habe ich dann in dem Load-Event der Form auch die Methode
BarcodeReaderRegisterMethods() aufgerufen.

Diese Methode habe ich in jeder Klasse definiert.

In den beiden Formen 1 und 3 gibt es die Methode BarcodeReader_OnRead, in dieser Methode werden spezielle Berechnung durchgeführt die in den Formen sehr unterschiedlich sind.

In der Form1 wird in dieser Methode auch die Anmeldedaten geprüft, bei positiver Prüfung die Methode 2 aufgerufen.

Das Deregistrien der Events für den Scanner mach ich in der Form3 im Closing-Event.



//so das ist im groben die erste Form

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:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
        /// <summary>
        /// Schließt die Anwendung bzw. verhindert das Schließen der Anwendung, wenn nicht
        /// der entsprechende Code <see cref="CLOSEAPPCODE"/> eingeben wurde.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void LogOnForm_Closing(object sender, CancelEventArgs e)
        {
            
            if (!appCanBeClosed)
            {
                e.Cancel = true;
            }

            BarcodeReaderDeregisterMethods(); //Events abmelden

            SingletonProvider<Symbol_Class>.Instance.TermReader(); //Scanner abmelden 
        }

        /// <summary>
        /// Aktiviert und konfiguriert den Barcode-Reader.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void LogOnForm_Load(object sender, EventArgs e)
        {                        
                  
            BarcodeReaderInit(); //initalisiert den Scanner

            BarcodeReaderRegisterMethods(); //Events registrieren
            SingletonProvider<Symbol_Class>.Instance.StartRead(); // Scanner aktivieren
        }

        /// <summary>
        /// Initialisiert und konfiguriert den Barcode-Reader.
        /// </summary>
        private void BarcodeReaderInit()
        {
            try
            {
                SingletonProvider<Symbol_Class>.Instance.InitReader();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        /// <summary>
        /// Registiert die Methoden, die aufgerufen werden sollen, wenn gescannt wird.
        /// </summary>
        private void BarcodeReaderRegisterMethods()
        {
            EventHandler evt = new EventHandler(this.BarcodeReader_OnRead);
            SingletonProvider<Symbol_Class>.Instance.AttachReadNotify(evt);

            EventHandler _evt = new EventHandler(this.myReader_StatusNotify);
            SingletonProvider<Symbol_Class>.Instance.AttachStatusNotify(_evt);
                    
        }

        //Status des Scanner ermitteln
        private void myReader_StatusNotify(object Sender, EventArgs e)
        {
            // Get ReaderData
            Symbol.Barcode.BarcodeStatus TheStatusData = SingletonProvider<Symbol_Class>.Instance.Reader.GetNextStatus();

            if (TheStatusData.State == States.READY || TheStatusData.State == States.IDLE)
                scannerstatus = true;
            else
                scannerstatus = false;

        }

        /// <summary>
        /// Deregistiert die Methoden, die aufgerufen werden, wenn gescannt wird.
        /// </summary>
        private void BarcodeReaderDeregisterMethods()
        {
            SingletonProvider<Symbol_Class>.Instance.StopRead();
            SingletonProvider<Symbol_Class>.Instance.DetachReadNotify();
            SingletonProvider<Symbol_Class>.Instance.DetachStatusNotify();           
        }

        /// <summary>5
        /// Reagiert auf das Scannen durch einen Endanwender.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="readerData"></param>
        //private void BarcodeReader_OnRead(object sender, EventArgs e)
        private void BarcodeReader_OnRead(object sender,EventArgs e)
        {
            ReaderData readerData = null;


            if (!scannerstatus)
                return;//kein Scan-Event

            try
            {
                SingletonProvider<Symbol_Class>.Instance.StopRead();
                readerData = SingletonProvider<Symbol_Class>.Instance.Reader.GetNextReaderData();                
            }
            catch(Exception ex)
            {
                MessageBox.Show(ex.Message);
                return;
            }

                             
            txtScannedEmployeeId.Text = readerData.Text;

            readerData = null;

            SqlCeDatabase MyDatabase = new SqlCeDatabase(SingletonProvider<Global>.Instance.SqlConnectionString);

            bool UserIsOK = MyDatabase.VerifyUserID(txtScannedEmployeeId.Text);
            SingletonProvider<Symbol_Class>.Instance.StartRead();
            if (UserIsOK == true)
            {
                stbMainForm.Text = String.Empty;
                this.textBox1.Text = MyDatabase.GetUserNameFromID(txtScannedEmployeeId.Text);
                LogOn(txtScannedEmployeeId.Text);
            }
            else
            {
                stbMainForm.Text = Strings.WARN_EMPLOYEEID_SCAN_WRONG;
                this.textBox1.Text = string.Empty;
            }
            MyDatabase = null;            
        }

        /// <summary>
        /// Schließt den Dialog und ruft den Menü Dialog auf.
        /// </summary>
        private void LogOn(String bcEmployeeID)
        {            

            Cursor.Current = Cursors.WaitCursor;
            MainForm mainForm = new MainForm();
            syData.userid = bcEmployeeID;
            try
            {
                
                BarcodeReaderDeregisterMethods();                
                mainForm.ShowDialog();
                
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                
            }

            mainForm.Dispose();

            Cursor.Current = Cursors.Default;

            BarcodeReaderRegisterMethods(); //events neu registrieren
            SingletonProvider<Symbol_Class>.Instance.StartRead();
            txtScannedEmployeeId.Focus();
        }


die Klasse Symbol sieht im auszugsweise so 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:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
  /// <summary>
  /// übergibt einen Event und speichert diesen in einer lokalen var
  /// </summary>
  public void AttachReadNotify(System.EventHandler ReadNotifyHandler)
  {
            // Ist der Scanner überhaupt initialisiert???
    if( Scanner != null)
    {
                
         // weißt den Event zu
      Scanner.ReadNotify += ReadNotifyHandler;
      myReadNotifyHandler = ReadNotifyHandler;

    }
  }

    /// <summary>
    /// löscht den Handler
    /// </summary>
    public void DetachReadNotify()
    {
            try
            {
                // Ist der Scanner überhaupt initialisiert??? und haben wir überhaupt ein zu löschendes Event
                if ((Scanner != null) && (myReadNotifyHandler != null))
                {
                    // löschen wir den mist
                    Scanner.ReadNotify -= myReadNotifyHandler;
                    //auch die lokale Variable
                    myReadNotifyHandler = null;
                   
                }
            }
            catch (Exception ex)
            {
            }
    }

        /// <summary>
        /// Attach a StatusNotify handler.
        /// </summary>
        public void AttachStatusNotify(System.EventHandler StatusNotifyHandler)
        {
            // If we have a reader
            if (Scanner != null)
            {
                // Attach status notification handler.
                Scanner.StatusNotify += StatusNotifyHandler;
                myStatusNotifyHandler = StatusNotifyHandler;
            }
        }

        /// <summary>
        /// löscht den Handler
        /// </summary>
        public void DetachStatusNotify()
        {
            try
            {
                // Ist der Scanner überhaupt initialisiert??? und haben wir überhaupt ein zu löschendes Event
                if ((Scanner != null) && (myStatusNotifyHandler != null))
                {
                    // löschen wir den mist
                    Scanner.StatusNotify -= myStatusNotifyHandler;
                    //auch die lokale Variable
                    myStatusNotifyHandler = null;

                }
            }
            catch (Exception ex)
            {
            }
        }
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4805
Erhaltene Danke: 1061

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Sa 25.06.11 08:48 
Hallo und guten Morgen Raorkon,

ok, der Scanner-Instanz (innerhalb der Klasse Symbol) werden also die Event-Methoden zugewiesen.
Wer jedoch ruft die Scanner-Methoden auf? Laufen diese in einem eigenen Thread?
Und kannst du diese dann debuggen?


BTW: dies ist mein 1000. Beitrag hier im Forum - juhu :dance2:
Raorkon Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 86
Erhaltene Danke: 1



BeitragVerfasst: Sa 25.06.11 10:26 
Guten morgen und Glückwunsch und ich fühle mich geehrt das du deinen 1000. Beitrag für mich geschrieben hast :D

die Scanner sind mit einem SDK eingebunden (Symbol), heißt ich kann diese auch nicht debuggen.

die Events werden auch zugewiesen das habe ich mehrmalig geprüft. Ich denke aber nicht das es ein Fehler des SDKs ist, denn wenn ich
die 1.Form dispose dann kann ich auch problemlos in der 3., 4.... Form scannen, jedoch muss ich jede Form in der ich gescannt habe schliessen.

Es gab auch einen Beispielcode von Symbol, aus diesen habe ich mir die Klasse Symbol erstellt. Einzigster Unterschied sind die Aufrufe des GC die ich nicht duchführe, das hat aber keinen Unterschied gemacht und aus den Postings die ich hier gelesen habe ist es eh nicht notwendig.

Ach ja wenn ich in der 1. Form nicht scanne, d.h. wenn ich den Event nicht auslöse, kann ich auch in der 3.Form scannen.

Oder sollte es doch am SDK liegen?
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4805
Erhaltene Danke: 1061

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Sa 25.06.11 13:19 
Hallo,

ja ich denke, das wird das Zusammenspiel des SDKs mit deinen 3 modalen Dialogen sein.
Jeder Aufruf per ShowDialog erzeugt eine eigene Message-Loop, anstatt daß nur die eine Message-Loop vom Application.Run() benutzt wird. Dies kann gerade in Verbindung mit externen SDKs Probleme bereiten (ich nehme mal an, daß das Scanner-SDK nativ in C bzw. C++ und nicht mit .NET-Mitteln programmiert wurde).
Darum habe ich als erstes ja auch geschrieben, daß du mal testweise mit Show() die Aufrufe durchführen solltest.

Du könntest ja ein pseudo-modales Verhalten simulieren, indem du das Close-Event abonnierst und vor dem Aufruf einfach die eigene Form deaktivierst (this.Enabled = false) und dann in der Close-Eventmethode dann diese wieder aktivierst.
Raorkon Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 86
Erhaltene Danke: 1



BeitragVerfasst: Sa 25.06.11 15:29 
okay dank dir für den Typ, werde ich nächste Woche gleich mal ausprobieren, Sobald ich ein Ergebnis habe melde ich mich
Raorkon Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 86
Erhaltene Danke: 1



BeitragVerfasst: Mo 04.07.11 05:57 
Hallo,

sorry erstmal für die späte Antwort, aber ein anderes Projekt hatte ersteinmal vorrang.

ich habe das Problem wie vorgeschlagen gelöst, in dem ich die Mainmaske mti Show() usw. aufgerufen habe.


Danke für deine Hinweise und Hilfe