[VC++ 2005] Vorgang für Abbruch

the incredible Leitman

Erfahrenes Mitglied
Jaja, ich weiß, dass der Titel nicht sehr aussagekräftig ist,
aber kP, was da besser passen würde -.-

Ich habe folgendes vor:
Über mein Programm sollen Daten an die USB Schnittstelle gesendet werden,
ausgelesen aus eine, Excel File, oder per Hand eingegeben.

Wenn ich einzelne Werte per Hand eingebe, ist das kein Problem,
Values in die Textboxen eintragen, senden drücken, erledigt.

Falls ich jedoch ein Array an Werten aus einem File auslese, sende ich alle Werte der Reihe nach.
Wenn es sich dabei um einige Hundert Werte handelt, kann das schon mal länger dauern...
In Windows ist da nun so, wenn das Programm beschäftigt ist
und ich drücke nochmals auf die Form (die ja gerade Unmengen an Daten sendet) steht auf der Taskleiste sowas wie "keine Rückmeldung"

Nun würde ich gerne eine Art Progress Bar einbaun, die den Fortschritt anzeigt, eventuell den momentan gesendeten Wert ( vl aber auch nicht, da das ungefähr im 10ms Zyklen abläuft) und einen "Abbrechen" Button.

Wie kann ich da vorgehen?

Also momentan gehe ich durch ne for Schleife, und sende jedes Element aus dem Array...

Hat jemand ne Idee, oder nur nen Denkanstoß, was man da machen könnte, dass der user den Vorgang jederzeit abbrechen kann?

Ich hoffe mir kann irgendjemand weiterhelfen,
Vielen Dank

mfG
Leitman
 
Frag doch einfach eine Variable ab, die der User über den Abbrechen Button setzt? Zum Beispiel kann beim OnClick Event die Variable auf 1 gesetzt werden und in jedem Schritt in der for Schleife wird diese Variable abgefragt. Ist sie != 1 geht's weiter bei == 1 machst du ein break um die Schleife zu beenden.

Edit: Hab grad erst gesehen, dass es sich um C++ handelt. Dann natürlich eine boolsche Variable.
 
Ach... ich bin ein Idiot -.-

Wollte das ganze über ein MessageBox machen :confused:
Also "MessageBox::Show("blub");" und wenn ich ein Dialog Result zurück bekomm, hör ich auf...

Aber mit einer Form sollte es gehen...

Wobei ich mir nicht sicher bin, ob das Programm Benutzereingaben abfangen kann, wenn ich mich in der for Schleife befinde...

werd das mal testen

Vielen Dank erstmal
the incredible Leitman
 
Hab mich soeben zuhause mal an den Laptop gesetzt und das probiert...

aber wirklich weiter gebracht hat mich das nicht -.-

Zurzeit habe ich folgende Struktur:
Bei Click auf den Sendebutton wird überprüft, ob es sich um nur einen oder um mehrere zu sendende Werte handelt, bei einem wird dieser sogleich gesendet, im Falle dass es sich um ein längeres Array handelt, öffne ich eine "Sending Form".

Nun habe ich das Problem, dass ich das senden sofort starten möchte, sobald die Form aufgeht, aber irgendwie bringe ich das nicht zusammen -.-

Entweder werden die Daten gesendet, noch bevor die Form zu senden ist:
Das passiert, wenn ich in den Event der Form das senden starte,
genauer im Load, GotFocus, HandleCreated, Invalidated oder VisibleChanged Event...

Kommt alles auf das selbe, ich öffne die Form mit "form->ShowDialog()",
die Daten werden gesendet und erst dann sehe ich dir Form erscheinen -.-

Wenn ich hingegen die Form mit "form->Show()" öffne, kann ich einfach in der nächsten Zeile im Code die Daten senden...
Dann wird die Form zwar zuerst geöffnet, aber nicht komplett... erst nach dem senden werden Buttons und Controls hinzugefügt -.-

Was mache ich falsch?
Wie funktioniert der richtig Weg?

Kann mir bitte vielleicht jemand helfen, wie ich vorzugehen habe?
Vielen Dank bereits im Vorraus
mfG
the incredible Leitman
 
Threading ist die Lösung. Somit wird der Senden-Vorgang Synchron zum Hauptprogramm gestartet und von der CPU abgearbeitet. Dadurch wird die GUI nicht Blockiert. Ich kann dir eine C# Klasse anbieten welche das ganze Vereinfacht. Da ich Managed C++ nicht wirklich beherrsche kann ich sie leider nicht umschreiben, sollte aber kein Problem für dich sein.

Klasse:
C#:
    /// <summary>
    /// Diese Klasse ermöglicht es Bytes in einen Stream 
    /// zu übertragen und den Vorgang zu überwachen. 
    /// </summary>
    public class ByteTransmitter
    {
        #region Felder
        private byte[] _axData;
        private Stream _oTarget; 
        #endregion

        #region Eigenschaften
        /// <summary>
        /// Ruft die zu sendenden Bytes ab oder legt diese fest. 
        /// </summary>
        public byte[] Data
        {
            get
            {
                return _axData;
            }
            set
            {
                _axData = value;
            }
        }
        /// <summary>
        /// Ruft den Stream in welchen die Bytes gesendet werden ab oder legt diesen fest. 
        /// </summary>
        public Stream Target
        {
            get
            {
                return _oTarget;
            }
            set
            {
                _oTarget = value;
            }
        } 
        #endregion

        #region Konstruktoren
        /// <summary>
        /// Initialisiert eine neue Instanz der <see cref="ByteTransmitter"> Klasse
        /// </summary>
        public ByteTransmitter()
            : this(null)
        {
        }

        /// <summary>
        /// Initialisiert eine neue Instanz der <see cref="ByteTransmitter"> Klasse
        /// </summary>
        /// <param name="axData">Die zu übertragenden Daten.</param>
        public ByteTransmitter(byte[] axData)
        {
            Data = axData;
        } 
        #endregion

        #region Methoden
        /// <summary>
        /// Startet den Vorgang um die Bytes zu übertragen.
        /// </summary>
        public void SendData()
        {
            // Alle Bytes durchlaufen
            for (int i = 0; i < _axData.Length; i++)
            {
                // Und in den Stream schreiben
                _oTarget.WriteByte(_axData[i]);
                // Event auslösen 
                OnStatusChanged(i);
            }
        } 
        #endregion

        #region Events
        /// <summary>
        /// Ein DelegatenTyp für die Statusabfrage.
        /// </summary>
        /// <param name="iBytesCurrent">Die Anzahl an Bytes welche bereits gesendet wurden.</param>
        /// <param name="iBytesTotal">Die Anzahl an Bytes welche insgesamt zu übertragen sind.</param>
        public delegate void ByteTransferEventHandler(int iBytesCurrent, int iBytesTotal);

        /// <summary>
        /// Löst das <see cref="StatusChanged"/> Event aus.
        /// </summary>
        /// <param name="iBytesCurrent">Die Anzahl an Bytes welche bereits gesendet wurden.</param>
        protected virtual void OnStatusChanged(int iBytesCurrent)
        {
            if (_evStatusChanged != null)
                _evStatusChanged(iBytesCurrent, Data.Length);
        }

        private event ByteTransferEventHandler _evStatusChanged;
        /// <summary>
        /// Wird ausgelöst wenn sich der Status der Übertragung geändert hat. 
        /// </summary>
        public event ByteTransferEventHandler StatusChanged
        {
            add
            {
                _evStatusChanged += value;
            }
            remove
            {
                _evStatusChanged -= value;
            }
        } 
        #endregion
    }

Demo-Anwendung:
C#:
        private ByteTransmitter _oTransmitter;
        private Thread          _oTransmission;

        private void button1_Click(object sender, EventArgs e)
        {
            // Dummy Bytes
            byte[] axData = new byte[1024];
            // Dummy Stream
            FileStream oTarget = new FileStream(@"C:\temp.dat", FileMode.OpenOrCreate);
            // Übertragung Initialisieren
            _oTransmitter = new ByteTransmitter(axData);
            _oTransmitter.Target = oTarget;
            // Handler Hinzufügen um den Status abzufragen
            _oTransmitter.StatusChanged += _oTransmitter_StatusChanged;
            // Übertragung in einem Neuen Thread starten
            _oTransmission = new Thread(_oTransmitter.SendData);
            _oTransmission.Start();
        }

        void _oTransmitter_StatusChanged(int iBytesCurrent, int iBytesTotal)
        {
            // Aktualisieren auslösen (ThreadÜbergreifend auslösen)
            progressBar1.Invoke(new ByteTransmitter.ByteTransferEventHandler(RefreshData), iBytesCurrent, iBytesTotal);
        }

        private void RefreshData(int iBytesCurrent, int iBytesTotal)
        {
            progressBar1.Maximum = iBytesTotal;
            progressBar1.Value = iBytesCurrent;
        }
Abbrechen kannst du den Vorgang in dem du die Methode Abort() des Thread Objekts aufrufst.

Ich empfehle dir trotzdem dich mal mit Threading zu beschäftigen.
Viel Glück.
 

Neue Beiträge

Zurück