none
Bitänderung - Event auslösen - Konzept RRS feed

  • Frage

  • Hallo,

    Bitconverter

    Bitconverter Helper class

    wie kann ich das am besten erreichen? Vermutlich durch die obigen Hilfsklassen.
    Ich habe ein DWORD value = 32775

    1000000000000111 = 32775Dez = 8007Hex

    Nun muss ich zyklisch prüfen, ändert sich was von 0 auf 1 oder von 1 auf 0.
    Sprich die Flanke, den Zustand.

    Bit 15 bis 0

    1001000010000111 = 36999Dez = 9087Hex

    Geändert also 12 und 7

    Ich benötige eine Funktion
       a) bool IsBitSet( int value )
            bool ret = IsBitSet(12)
                  -> ret = 1
       b) Einen Event, Delegate auslösen, bei positiver, negativer Änderung.  
           Das ist nicht so einfach. Was bietet sich hier an?       
           
    Grüße Andreas

    Donnerstag, 4. Oktober 2012 15:10

Antworten

  • Hallo Andreas,

    Du musst keine 16 Eingänge erkennen/behandeln, sondern vergleichen, was sich wo geändert hat. Das erreichst Du ganz sicher nicht mit einem Einzeiler.

    Ich poste dir nachstehend zwei Klassen für die Speicherung und dazu ein Formular. Ist zwar in VB, der Code sollte sich aber problemlos übersetzen lassen. Bevor mich nun einer schlägt: Mir ist bewusst, dass man das besser machen kann, allerdings denke ich, dass man die Komplexität nicht noch mehr erhöhen sollte, sonst wir das hier wahrscheinlich gar nix mehr^^

    Public Class ValueChangedEventArgs
    
        Protected OldBits    As BitArray
        Protected NewBits    As BitArray
    
        Private _OldValue    As Int16
        Private _NewValue    As Int16
        Private _ChangedBits As List( Of BitChangedEventArgs )
    
        Public ReadOnly Property OldValue As Int16
            Get
                Return _OldValue
            End Get
        End Property
    
        Public ReadOnly Property NewValue As Int16
            Get
                Return _NewValue
            End Get
        End Property
    
        Public ReadOnly Property ChangedBits As List( Of BitChangedEventArgs )
            Get
                Return _ChangedBits
            End Get
        End Property
    
        Public Sub New( ByVal OldValue As Int16, ByVal NewValue As Int16 )
    
            Me._OldValue    = OldValue
            Me._NewValue    = NewValue
            Me._ChangedBits = New List(Of BitChangedEventArgs )()
    
            Me.OldBits = New BitArray( BitConverter.GetBytes( OldValue ) )
            Me.NewBits = New BitArray( BitConverter.GetBytes( NewValue ) )
    
            For Counter As Int32 = 0 To Me.OldBits.Count - 1
                Me._ChangedBits.Add( New BitChangedEventArgs( Counter, Me.OldBits( Counter ), Me.NewBits( Counter ) ) )
            Next
    
        End Sub
    
    End Class

    Diese Klasse speichert die Werte zu den gegebenen Zahlen und ermittelt aus altem und neuen Wert dann die jeweiligen Bits.

    Public Class BitChangedEventArgs
    
        Private _Index    As Int32
        Private _OldValue As Boolean
        Private _NewValue As Boolean
        Private _Changed  As Boolean = False
    
        Public ReadOnly Property Index As Int32
            Get
                Return _Index
            End Get
        End Property
    
        Public ReadOnly Property OldValue As Boolean
            Get
                Return _OldValue
            End Get
        End Property
    
        Public ReadOnly Property NewValue As Boolean
            Get
                Return _NewValue
            End Get
        End Property
    
        Public ReadOnly Property Changed As Boolean
            Get
                Return _Changed
            End Get
        End Property
    
        Public Sub New( ByVal Index As Int32, ByVal OldValue As Boolean, ByVal NewValue As Boolean )
    
            Me._Index    = Index
            Me._OldValue = OldValue
            Me._NewValue = NewValue
    
            If _OldValue <> _NewValue Then
                Me._Changed = True
            End if
    
        End Sub
    
    End Class

    Diese Klasse dient nur dazu, die Zustände der einzelnen Bits zu speichern. Eine List( Of ... ) wird hierfür dann in der Klasse ValueChangedEventArgs integriert, dort sind die Werte dann abrufbar.

    Public Class Form1
    
        Protected SavedValue As Int16
    
        Public Event ValueChanged( ByVal sender As Object, ByVal e As ValueChangedEventArgs )
    
        Private Sub Button1_Click( sender As System.Object,  e As System.EventArgs) Handles Button1.Click
    
        Dim NewValue As Int16
    
            Int16.TryParse( Value.Text, NewValue )
    
            If SavedValue <> NewValue Then
                RaiseEvent ValueChanged( Me, New ValueChangedEventArgs( SavedValue, NewValue ) )
                SavedValue = NewValue
            End If
    
        End Sub
    
        Public Sub Form_ValueChanged( ByVal sender As Object, ByVal e As ValueChangedEventArgs ) Handles Me.ValueChanged
    
        Dim Message As String = String.Empty
            For Each Item As BitChangedEventArgs In e.ChangedBits.FindAll( Function( Check ) Check.Changed = True )
                Message &= String.Format( "Bit an Stelle {1} wurde von Wert {2} in Wert {3} geändert{0}", ControlChars.NewLine, Item.Index, IIf( Item.OldValue, "1", "0" ), IIf( Item.NewValue, "1", "0" ) )
            Next
            MessageBox.Show( String.Format( "Alter Integer Wert: {1}{0}Neuer Wert: {2}{0}{0}{3}", ControlChars.NewLine, e.OldValue.ToString(), e.NewValue.ToString(), Message ) )
    
        End Sub

    Leg dir im Testprojekt bitte eine Form "Form1" an und bau dort eine Textbox mit dem Namen "Value" ein. Wenn Du das Testprojekt gestartet hast, gib einfach mal verschiedene Zahlen im Bereich von 0 bis 32767 ein und schau, was dabei herauskommt. Danach setzt Du an für dich interessanten Stellen Breakpoints und schaust dir genauer an, was die einzelnen Codeteile eigentlich tun und vor allem, wie.

    Und in die letzte Schleife, die die Elemente durchläuft, die sich geändert haben, kommt dann deine Abfrage von oben (also prüfen auf alter Wert 0, neuer Wert 1, usw.) mit anschließendem Aufruf deiner eigenen Methoden rein.

    ---

    Und ja, ich weiß, dass ich gerade meinen eigenen Krams von eben übern Haufen geworfen habe :)


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community


    Samstag, 6. Oktober 2012 19:52
    Moderator
  • Hallo Andreas,

    Einspruch: Ich bin ein Freund von Bildern, vorzugsweise ausdrucksstarken, z. B. Impressionisten, Expressionisten uvm.

    Er ist kein Freund von Hardcopies mit der Frage: Siehst Du den Fehler? - was ich umschrieben hatte mit Enthusiasmus vermissen.

    Bei Sätzen wie ok, ich muss den int Wert umwandeln in binär, bleibt mir jedoch die Spucke weg. Zur anscheinend notwendigen Aufklärung:
    Warum benutzen Computer nicht das Dezimalsystem?

    Da Du anscheinend nicht begreifen kannst, das wir hier einen Zwergenaufstand um nichts machen, ein (letztes) Beispiel.

    Ich habe auf das Ereignis verzichtet und dafür die Arbeiter direkt in eine Liste gesteckt. Die Verarbeitung erfolgt in einer (trivialen) Schleife, die ihre Eingaben über IEnumerable bezieht. Alternativ könnte hier ein Stream, eine Queue, eine IProducerConsumer uvm. stehen.

    Was alles nur Brimborium ist, die gesamte Logik steckt in der Zeile:

    int state = (prevState ^ newState) & this.BitMask;

    Und um zu zeigen, das es (binär) so simpel funktioniert gibt es eine auf die Logik reduzierte Version FürAnfänger am Anfang.

    using System;
    using System.Collections.Generic;
    
    namespace ElmarBoye.Samples.Code
    {
        internal static class TestBits
        {
            internal static void Run()
            {
                // beide zusammen
                FürAnfänger();
                RunEngine();
            }
    
            /// <summary>
            /// Führt die Tests für die Bitmasken der unten implementierten WorkerA..C aus.
            /// </summary>
            internal static void FürAnfänger()
            {
                // zweimal je ein Bit, dann beide zusammen (siehe Worker A, B, C)
                var bitMasks = new int[] { 0x1000, 0x0200, 0x1200 }; 
                foreach (var bitmask in bitMasks)
                {
                    Console.WriteLine("Bitmask is {0:X4}", bitmask);
                    FürAnfänger(bitmask);
                }
            }
    
            /// <summary>Binäre Logik für Anfänger oder wie testet man Bits...</summary>
            /// <seealso cref="http://de.wikipedia.org/wiki/Bitweiser_Operator"/>
            private static void FürAnfänger(int bitMask)
            {
                int prevState = 0;
                foreach (int newState in SimpleStateInput())
                {
                    int evalState = (prevState ^ newState) & bitMask;
                    Console.WriteLine("Prev: {0:X4}, New: {1:X4}, Result: {2:X4} ({3})", prevState, newState, evalState, evalState != 0);
                    if (evalState != 0)
                    {
                        prevState = newState & bitMask;
                    }
                }
            }
    
            /// <summary>Startet die Beispiel Engine.</summary>
            internal static void RunEngine()
            {
                var engine = new StatusWorkerEngine();
                engine.Worker.Add(new ConsoleStatusWorker("Worker A", 0x1000));
                engine.Worker.Add(new ConsoleStatusWorker("Worker B", 0x0200));
                engine.Worker.Add(new ConsoleStatusWorker("Worker C", 0x1200));
    
                Func<IEnumerable<int>> input = SimpleStateInput;
                //Func<IEnumerable<int>> input = RandomStateInput;
                engine.Execute(input);
            }
    
            /// <summary>Liefert eine Anzahl von Integern.</summary>
            private static IEnumerable<int> SimpleStateInput()
            {
                // Für Worker A..C 
                int[] states = new int[] { 0x1000, 0x1100, 0x0200, 0x02FF, 0x12FF, 0x1200, 0x1000, 0x00FF };
                
                for (int index = 0; index < states.Length; index++)
                    yield return states[index];
            }
    
            /// <summary>Liefert 1000 Integer.</summary>
            /// <param name="count">Anzahl von Elementen</param>
            private static IEnumerable<int> RandomStateInput()
            {
                int count = 1000;
                var random = new Random();
                while (count > 0)
                {
                    count--;
                    int state = random.Next(0, 0xffff);
                    yield return state;
                }
            }
        }
    
        /// <summary>
        ///  (BASIS)-Klasse für die Verarbeitung anhand von Statusänderungen.
        /// </summary>
        public class StatusWorker
        {
            const int MAXSTATEBITS = 0xffff; // 16-Bit-Word
    
            /// <summary>Name für Ausgaben.</summary>
            public string Name { get; private set; }
            /// <summary>Die zu berücksichtigen Bits (Word).</summary>
            public int BitMask { get; private set; }
            /// <summary>Letzter Status.</summary>
            public int LastState { get; private set; }
    
            /// <summary>Erzeugt einen Worker mit einem Namen und einer BitMask.</summary>
            /// <param name="name"></param>
            /// <param name="bitMask"></param>
            protected StatusWorker(string name, int bitMask)
            {
                this.Name = name ?? String.Empty;
                this.BitMask = (bitMask & MAXSTATEBITS);
            }
    
            /// <summary>Von der Engine aufgerufen.</summary>
            internal void Execute(int state)
            {
                state &= MAXSTATEBITS;
                if (ShouldExecuteState(state))
                {
                    this.ExecuteState(state);
                    this.LastState = (state & this.BitMask);
                }
            }
    
            /// <summary>Testet, ob die Bedingungen zutreffen.</summary>
            protected virtual bool ShouldExecuteState(int state)
            {
                int evalState = GetMaskedState(this.LastState, state);
                return (evalState != 0);
            }
    
            /// <summary>Führt Sinnvolles aus...</summary>
            protected virtual void ExecuteState(int state)
            {
            }
    
            /// <summary>Testet auf BitMask, und der Grund des Unterfangens!</summary>
            protected int GetMaskedState(int prevState, int newState)
            {
                int state = (prevState ^ newState) & this.BitMask;
                return state;
            }
    
            /// <summary>Von der Engine zu Anfang aufgerufen, führt Initialisierungen durch.</summary>
            public virtual void Initialize()
            {
                this.LastState = 0;
            }
    
            /// <summary>Von der Engine am Ende aufgerufen, führt Aufräumarbeiten durch.</summary>
            public virtual void Shutdown()
            {
                this.LastState = -1;
            }
        }
    
        /// <summary>Exemplarische Implemenation für eine Konsolenausgabe.</summary>
        public class ConsoleStatusWorker : StatusWorker
        {
            public ConsoleStatusWorker(string name, int bitMask)
                : base(name, bitMask)
            {
            }
    
            /// <summary>Protokolliert auf Console.</summary>
            protected override bool ShouldExecuteState(int state)
            {
                bool shouldExecute = base.ShouldExecuteState(state);
                Console.WriteLine("\t{0} ShouldExecute: {1:X4} == {2:X4} ({3})", this.Name, this.LastState, state, shouldExecute);
                return shouldExecute;
            }
    
            /// <summary>Führt irgendetwas aus (hier eine Console-Ausgabe)</summary>
            protected override void ExecuteState(int state)
            {
                int newState = GetMaskedState(this.LastState, state);
                Console.WriteLine("\t{0} Execute      : {1:X4} => {2:X4}", this.Name, this.LastState, newState); 
            }
        }
    
        /// <summary>Primitive Engine, die die Arbeit an StatusWorker delegiert.</summary>
        public class StatusWorkerEngine
        {
            public StatusWorkerEngine()
            {
                this.Worker = new List<StatusWorker>();
            }
    
            public List<StatusWorker> Worker { get; private set; }
    
            public void Execute(Func<IEnumerable<int>> input)
            {
                if (input == null)
                    throw new ArgumentException("I need some input!");
    
                // Initialisierung
                foreach (var workerItem in this.Worker)
                    workerItem.Initialize();
    
                // Eingaben an die Worker übergeben
                foreach (int state in input.Invoke())
                {
                    Console.WriteLine("\n***Engine START: {0:X4}", state);
                    
                    foreach (var workerItem in this.Worker)
                        workerItem.Execute(state);
    
                    Console.WriteLine("***Engine END : {0:X4}", state);
                }
    
                // Aufräumen
                foreach (var workerItem in this.Worker)
                    workerItem.Shutdown();
            }
        }
    }

    Damit ist der Thread und das Thema für mich abgeschlossen.
    Weitere Antworten werde ich erst geben, wenn ich substantielle Eigenleistungen auf Deiner Seite erkennen kann.

    Gruß Elmar

    • Bearbeitet Elmar BoyeEditor Sonntag, 7. Oktober 2012 15:45 kursiv ist kursiv, egal was das "Branding" sagt.
    • Als Antwort markiert Andreas Bauer2 Montag, 8. Oktober 2012 10:41
    Sonntag, 7. Oktober 2012 15:41
    Beantworter


  • Gehört nicht direkt zu diesem Thread.
    Wenn Du eine bessere Möglichkeit siehst, die Formatierung zu machen, sage ich im Voraus Danke.   Siehe Markierung !!!!!!!!!!!!!

    String Binär mit führenden Nullen



    Hi,
    char pad = '0';
    binaerOldValueMessage = binaerOldValue.PadLeft(16, pad);
    binaerNewValueMessage = binaerNewValue.PadLeft(16, pad);
    MSDN

    Hope to help, Oliver

    Dienstag, 9. Oktober 2012 10:04

Alle Antworten

  • Hallo, Ich muss sagen, das verwirrt schon ganz schön.

      • 8 Bits ergeben 1 Byte. Nur um das zu 101% sicher zu stellen ;)
      • Machst du C# oder C++? DWORD in C#
      • bool IsBitSet( int value )
                bool ret = IsBitSet(12)
                      -> ret = 1
        Wovon soll das 12. Bit gesetzt sein?

    a) Ich würde so etwas da machen. Ich kann duir nicht garanetieren, das es am effektivsten ist, aber es funktioniert:

    if(IsBitSet(value, bit))
    {
    //...
    }
    
    bool IsBitSet(int value, uint bit)
    {
        if(ToBin(value).ToCharArray()[bit] == '1')
    return true;
    return false; }

            private string ToBin(int dec)
            {
                if (dec == 0)
                    return "0";

                int dec2 = dec / 2;
                return ToBin(dec2) + dec % 2;
            }

    b) Ein Event??? Ein Tutorial dazu:
    http://msdn.microsoft.com/en-us/library/aa645739%28v=vs.71%29.aspx

    Oder mal ganz kurz zusammen gefasst:

    EventHandler<EventArgs> ChangeToZero;
    
    private void Change()
    {
        //Änderugn des Bits...
        var v = ChangeToZero;
        if(var != null)
            var(this, new EventArgs);
    }
    EventArgs kannst du auch gegen eine Eigene von EventArgs abgeleitete Klasse austauschen.


    Koopakiller - http://koopakiller.ko.ohost.de/

    Donnerstag, 4. Oktober 2012 15:33
    Moderator
  • Hallo Andreas,

    naja, das sind Grundlagen - erste Klasse - zumindest wer C(++) behauptet zu können.
    Und vor einem Jahr hatten wir schon ein ähnliches Spielchen:
    CheckBitSet nach Vorgabe eines Integer Wertes, BitSet in C#?

    (und nein, da gibt es keine neuen Forschungsergebnisse ;-))

    a) Einfachste Xor Variante mit einem int  oder uint, wenn es dem DWORD entsprechen muss:

                int prevState = 0x8007;
                int newState = 0x9087;
                int changedBits = prevState ^ newState;
                Console.WriteLine("Changed {0:x2} / {1}", changedBits, Convert.ToString(changedBits, 2));
    
    Und wenn Du jedes Bit einzeln zerlegen willst, schau Dir das BitArray (oder wie schon mal den BitVector32) an.

    b) Was das Ereignis angeht:
    Definiere ein EventArgs mit den ChangedBits, d. h. einem schlichten (u)int, und versende es.
    Ein Xor sollte auch jeder Empfänger hinkriegen, so denn in der ersten Klasse gewesen.
    Wie man das macht steht bei Ereignisse (C#-Programmierhandbuch)

    Gruß Elmar

    Donnerstag, 4. Oktober 2012 16:23
    Beantworter

      • Wovon soll das 12. Bit gesetzt sein?

    Hallo  Koopakiller,

    in C#

    SPS-BIT-Driver

    es gibt eine neue TCP-SPS. Leider ohne vernünftigen Treiber. Sprich ich muss mir über einen BackgoundThread den Wert auslesen, entscheiden pos./neg. Flanke.

    Sicher unschön. Deshalb die Frage nach den Events, wie man das elegant lösen kann.

    Das Bit wird durch eine Sensorik gesetzt. Für Testzwecke. Usereingabe.

    Wenn Du noch Ideen, Konzepte hast, sehr gerne.

    Dein Ansatz zu Elmar ist nicht gleich. Siehst Du den Fehler?

    BIT

    Grüße Andreas

       private void btnTestBitConverter_Click(object sender, EventArgs e)
            {
                // XOR 
                // http://msdn.microsoft.com/de-de/library/vstudio/zkacc7k1%28v=vs.90%29.aspx
                // http://msdn.microsoft.com/de-de/library/vstudio/system.collections.bitarray%28v=vs.100%29.aspx
    
    
                int prevState = 0x8007;
                int newState = 0x9087;
                int changedBits = prevState ^ newState;
                Console.WriteLine("Changed {0:x2} / {1}", changedBits, Convert.ToString(changedBits, 2));
    
                bool ret = IsBitSet(changedBits, 12);
    
            }
    
            private string ToBin(int dec)
            {
                if (dec == 0)
                    return "0";
    
                int dec2 = dec / 2;
                string ret = ToBin(dec2) + dec % 2;
                return ret;
            }
    
            bool IsBitSet(int value, uint bit)
            {
                char[] bitArray; // = new char(1024);
                //char bit;
                
                //bitArray = ToBin(value).ToCharArray()[bit];
                bitArray = ToBin(value).ToCharArray();
                if (bitArray[bit] == '1')
                    return true;
                return false;
            }


    Freitag, 5. Oktober 2012 08:27

  • b) Was das Ereignis angeht:
    Definiere ein EventArgs mit den ChangedBits, d. h. einem schlichten (u)int, und versende es.
    Ein Xor sollte auch jeder Empfänger hinkriegen, so denn in der ersten Klasse gewesen.
    Wie man das macht steht bei Ereignisse (C#-Programmierhandbuch)

    Hallo Elmar,

    ja, die Punkte mit dem Ereignis (pos./neg. Zustandsänderung) da hänge ich halt.

    Sonst siehe noch vorherige Antwort. Ein konkreter Ansatz noch....?

    Nach jeder Zustandsänderung, und nur dann soll der Event ausgelöst werden.

    Siehe Bild.

    Danke im Voraus.

    Grüße Andreas

    Bild pollen

    public partial class Form1 : Form
        {
            BitVector32 MyPrevState ;
            BitVector32 MyNewState ;
            BitVector32 MyChangeState;
    
            EventHandler<EventArgs> ChangeToZero;
    
            public Form1()
            {
                InitializeComponent();
            }
    
            private void btnTestBitConverter_Click(object sender, EventArgs e)
            {
                // XOR 
                // http://msdn.microsoft.com/de-de/library/vstudio/zkacc7k1%28v=vs.90%29.aspx
                // http://msdn.microsoft.com/de-de/library/vstudio/system.collections.bitarray%28v=vs.100%29.aspx
    
    
                int prevState = 0x8007;
                int newState = 0x9087;
                int changedBits = prevState ^ newState;
                Console.WriteLine("Changed {0:x2} / {1}", changedBits, Convert.ToString(changedBits, 2));
    
                bool ret = IsBitSet(changedBits, 12);
    
    
                MyPrevState = new BitVector32(prevState);
                MyNewState = new BitVector32(newState);
                MyChangeState = new BitVector32(MyPrevState.Data ^ MyNewState.Data);
              
            }
    
            private void Change()
            {
                //Änderugn des Bits...
                var v = ChangeToZero;
                if(v != null)
                    v(this, new EventArgs());
            }
    
            private string ToBin(int dec)
            {
                if (dec == 0)
                    return "0";
    
                int dec2 = dec / 2;
                string ret = ToBin(dec2) + dec % 2;
                return ret;
            }
    
            bool IsBitSet(int value, uint bit)
            {
                char[] bitArray; // = new char(1024);
                //char bit;
    
                //bitArray = ToBin(value).ToCharArray()[bit];
                bitArray = ToBin(value).ToCharArray();
                if (bitArray[bit] == '1')
                    return true;
                return false;
            }
    
        }


    • Bearbeitet Andreas Bauer2 Freitag, 5. Oktober 2012 10:36 Bild fehlte
    Freitag, 5. Oktober 2012 08:30
  • Hallo Andreas,

    Du hängst an sehr vielen Stellen ;)
    Willst Du ernsthaft Bits über CharArrays auswerten???
    Schaut man darauf, was Du oben produziert hast, droht vor lauter Kopfschütteln eine Genickstarre...

    Jemand der sich mit SPS Programmierung beschäftigt, sollte schon mit dem einen oder anderen Bit umgehen können. Und ich - der mit SPS überhaupt nichts am Hut hat -  erkennt nach 5 Minuten Beschäftigung mit dem Programmers Manual, dass man dort mit nativen (16 Bit) Worten arbeiten sollte. Schickt man jedes "Bit" einzeln als Ereignis durch die Welt, so überflutet man nur den Empfänger.

    Um etwas mit Nährwert zu produzieren, als Vorschlag:

        public class BitChangedEventArgs : EventArgs
        {
            private int _data;
            
            /// <summary>Erstellt Ereignisargumente als Integer Wert</summary>
            /// <param name="data">Ein Integer max. 16 Bits.</param>
            public BitChangedEventArgs(int data)
            {
                this._data = (data & 0xffff);   // max. 16 Bit
            }
    
            /// <summary>Erstellt die Ereignisargumente als Xor Verknüpfugn.</summary>
            /// <param name="oldData">Vorheriger Zustand.</param>
            /// <param name="newData">Neuer Zustand</param>
            public BitChangedEventArgs(int oldData, int newData)
                : this(newData ^ oldData)
            {
            }
    
            /// <summary>Liefert die Daten als Integer.</summary>
            public int Data
            {
                get { return this._data; }
            }
    
            /// <summary>Liefert ob ein Bit gesetzt ist oder nicht.</summary>
            /// <param name="index">Im Bereich von 0..15.</param>
            public bool this[int index]
            {
                get 
                {
                    if (index < 0 || index > 15)
                        throw new ArgumentOutOfRangeException("index");
                    return ((this._data & (1 << index)) != 0);
                }
            }
    
            public override string ToString()
            {
                return this.GetType().Name + "[0x" + this._data.ToString("X4") + "]";
            }
        }
    

    Und für die "Testdaten" von gestern z. B.:

                int prevState = 0x8007;
                int newState = 0x9087;
                var eventData = new BitChangedEventArgs(prevState, newState);
                Console.WriteLine("Data: " + eventData);
                for (int index = 0; index < 16; index++)
                    Console.WriteLine("Bit {0}: {1}", index, eventData[index]);
    
    Wobei es später irgendwo einen Eventhandler geben wird:
    private EventHandler<BitChangedEventArgs> _bitsChanged;

    Aber offen gesprochen: Wenn Du bereits an solchen Kleinigkeiten scheiterst, solltest Du da Programmieren eines "Treibers" jemanden überlassen, der etwas mehr davon versteht.

    Gruß Elmar

    Freitag, 5. Oktober 2012 10:48
    Beantworter
  • Hallo Elmar,
    >Willst Du ernsthaft Bits über CharArrays auswerten???
    Ich suche ja Ansätze, da ich es noch nie gemacht habe.
    Deine Lösung ist besser, ist sauber. Muss man wissen. Koopakiller wusste es vielleicht auch nicht.
    >Aber offen gesprochen: Wenn Du bereits an solchen Kleinigkeiten scheiterst,
    >solltest Du da Programmieren eines "Treibers" jemanden überlassen,
    >der etwas mehr davon versteht.
    Ich muss ja irgendwann mal anfangen.

    private EventHandler<BitChangedEventArgs> _bitsChanged;

    Da hänge ich noch.

    Ich muss mir ja die alten Zustände, alle 16 merken und nur bei Änderungen den positiven, negativen Event auslösen. Wie macht man das richtig. Bestimmt weißt du das und recht schnell.

    Danke für den Tipp.

    Grüße Andreas

    Freitag, 5. Oktober 2012 11:31
  • Hallo Andreas,

    Du suchst nach Problemen, wo (für mich) keine sind.
    Wenn Du nur auf Änderungen reagieren willst, so speichere den Wert in einem Integer Wert - wie oben gezeigt als prevState.
    Solange der Lesevorgang das gleiche liefert (prevState == newState) passiert nichts, wenn ungleich (!=) so löst Du ein "Ereignis" aus.
    Dann merken des Zustandes und das Spiel beginnt von vorne.

    Wie man Ereignisse kodiert steht im bereits genannten Link. Und ich rate Dir dringend an, das mal zu lesen - man hat immer den Eindruck Du drückst Dich davor (und malst lieber Bildchen). Ansonsten verweise ich auf einen Thread, in dem ich vor kurzem Grundlagen "doziert" hatte:

    Musterbeispiele für Events, Delegate, Action

    Da ich aber letztendlich nicht weiß, was Du überhaupt anstellen willst - und ich keinen Schnelleinstieg in die SPS Programmierung vorhabe -  kann ich ansonsten nicht wirklich helfen.

    Was Koopakiller's Antworten angeht:
    Er konnte genauso wenig wissen wie ich, was Deine Intention ist. Und Fragen wie Antworten, die ich im letzten Jahr von ihm im Forum gesehen habe, zeigen schnelle Fortschritte und Engagement.[1]

    Deine Fragen hingegen, die Du seit einigen Jahren - hier und bereits in den Newsgroup - periodisch in Variationen wiederholst, lassen jeden Enthusiasmus vermissen. Was ich bedauere, aber nicht ändern kann, das musst Du selbst tun.

    Gruß Elmar

    [1] @Koopakiller:
    Als Hinweis einige Standardoperationen, die bei Bit-Arithmetik immer wieder vorkommen:

                int value = 0x8007;
                int bit = 12;
    
                value |= (1 << bit);    // Set Bit
                int bitToGet = value & (1 << bit);    // Get Bit
    
                // weitere Standardoperationen
                value &= ~(1 << bit);   // Clear Bit
                value = ~value & 0xffff; // Negate 16 Bit
    Als Integer-Operationen - auch wenn hier eigentlich 16-Bit (short) angesagt war, da die .NET IL auf 32-Bitoperationen ausgelegt ist - als Beispiel z. B. der oben häufiger verwendete SHL-Opcode (C# <<).  (Und mit 16 Bit-Worten arbeitet heute meist nur noch die Steuerungstechnik).

    Freitag, 5. Oktober 2012 13:19
    Beantworter
  • Du suchst nach Problemen, wo (für mich) keine sind.
    Wenn Du nur auf Änderungen reagieren willst, so speichere den Wert in einem Integer Wert - wie oben gezeigt als prevState.
    Solange der Lesevorgang das gleiche liefert (prevState == newState) passiert nichts, wenn ungleich (!=) so löst Du ein "Ereignis" aus.
    Dann merken des Zustandes und das Spiel beginnt von vorne.

    Hallo Elmar,

    wenn ungleich muss ich das Ergeignis auslösen. Keine Frage.

    Ich möchte jedoch wissen ist das Ereignis

    Von_1_Auf_0_Bit_12   - Negativ

    Von_0_Auf_1_Bit_12    - Positiv

    Wo ich hänge nun.

    Wie kann ich das realisieren.

    Alle Bits in eine Liste, bei Zustandsänderung dann den Event auslösen.

    Oder so eine Art MessageMap.

    Da benötige ich Hilfe.

    Im Endeffekt habe ich dann 16 'positive' Funktionen

    Im Endeffekt habe ich dann 16 'negative' Funktionen

    Grüße Andreas

    Freitag, 5. Oktober 2012 19:36
  • Hallo Andreas,

    wozu willst Du "negative" / "positive" Funktionen und wozu für jedes Bit einzeln?

    Führst Du für jede Variante ein Ereignis ein, so gibt es reichlich viel Overhead bei der Verarbeitung (und die funktioniert nur schlechter).

    Wie mehrfach gezeigt, ist es mit etwas Bitarithmetik kein Problem für einen Empfänger (wer auch immer das sein mag), sich die notwendigen Informationen zu beschaffen. Jeder Empfänger kann seinen letzten Status merken und mit einem einfachen Vergleich bestimmen, ob er weitermacht oder das Ereignis ignoriert.

    Will man Empfänger bereits vorm Verteilen filtern, könnte man mit Lambdas Prädikate (wie Predicate<T>) verwenden. Einen großen Vorteil sehe ich darin aber nicht, solange Du nicht hunderte von Empfängern hast. (Windows produziert auch viele WM_MOUSEMOVE uvm. ohne sich dafür zu interessieren, ob es überhaupt Empfänger dafür gibt.)

    Es gibt zwar andere Konzepte wie die Reactive Extensions - aber abgesehen davon, dass sie .NET 4.5 bevorzugen -, würden sie Dich beim derzeitigen Stand wohl vollständig überfordern.

    Gruß Elmar

    Freitag, 5. Oktober 2012 20:48
    Beantworter
  • Hallo Elmar,

    schön wie Du mein Nichtwissen jedesmal erwähnt.

    Ja ich weiß es nicht, wie man es optimal macht, deshalb frage ich nach.

    Es konkret am Beispiel zu tun ist nicht so einfach. Overhead will niemand.

    Eine einfache Änderung, den Event auszulösen, ist ok.

    Ich muss aber von 0->1 Etwas tun    und von 1->0 Etwas anders tun.

    Für 16 Eingänge, da ist das Problem und suche ein brauchbares Konzept.

    Genau, wenn die Zustandsänderung eintritt muss ich was tun, nicht irgendwann. Nach wie vor wäre es nett, wenn Du ein gutes Konzept aufzeigen könntest. Hoffe nun, dass es klar ist, was ich benötige.

    Schönes Wochenende noch....

      Andreas

    -- Danke im Voraus -- Ich weiß dass Du es elegant lösen kannst


    • Bearbeitet Andreas Bauer2 Samstag, 6. Oktober 2012 07:06 Formatierung
    Samstag, 6. Oktober 2012 06:59
  • Hi Andreas,
    Elmar hat Dir doch den prinzipiellen Weg gezeigt.
     
    Die Änderung eines einzelnen Bits ändert den Gesamtzustand (Byte, Wort, Doppelwort o.ä., je nach Anzahl der gelieferten Bits). Das heißt, es gibt nur ein Ereignis und egal, welches Bit sich ändert, es wird immer das gleiche Ereignis ausgelöst. Dieses Ereignis konsumiert ein Manager, der das Ereignis an den konkreten Verbraucher weiterleitet. Jeder konkrete Verbraucher registriert sich beim Manager mit einem Delegaten und einer Beschreibung der Zustandsänderungen, auf die zu reagieren ist (welche Bits bzw. Bitkombinationen von welchem alten Zustand zu welchem neuen Zustand). Jeder Verbraucher ist ein Objekt vom Typ einer Klasse, die von einem Basistyp erbt, mit dem der Manager unabhängig vom konkreten Verbraucher arbeiten kann. Mit dieser Verfahrensweise bist Du flexibel, kannst auf Veränderungen reagieren, kannst dynamisch das Verhalten ändern, kannst mehrere Empfänger für die gleiche Veränderung binden, kannst einen Verbraucher für unterschiedliche Änderungen nutzen, kannst gut kapseln.
     
    Versuche mal, dieses einfache Konzept umzusetzen, und melde Dich mit konkretem Code und einer Beschreibung des Problems, was Du dabei hast.
     
    --
    Viele Gruesse
    Peter
    Samstag, 6. Oktober 2012 08:35
  • Hallo Peter,

    Danke für die Antwort.

    Elmar ist kein Freund von Bildern. Ich denke dennoch, dass es hilfreich ist das logische Modell aufzuzeichnen, sprich wie ich es angedeutet habe. (siehe oben) Dein Tipp mit dem Manager ist ja ok, kannst Du dennoch mal aufzeichen, wie das logische Modell, welche Klassen man benötigt.

    Von 0->1 Etwas tun und von 1->0 Etwas anders tun.

    Grüße Andreas

    Samstag, 6. Oktober 2012 16:05
  • Hallo Andreas,

    Elmar ist kein Freund von Bildern.

    ich denke eher, dass Elmar damit meinte, dass Du oftmals immer wieder dieselben Fragen stellst und auch für mich hat es eher den Eindruck, dass Du "ein wenig" Probleme hast, das, was man die antwortet, dauerhaft umzusetzen. Denn viele deiner Fragen wiederholen sich bzw. hätten die gleiche Lösung, die Du aber anscheinend nicht umsetzen kannst/willst.

    Es ist gar kein Problem, wenn jemand etwas nicht weiß. Es ist aber ärgerlich und auch ziemlich nervig, wenn man jemandem immer und immer wieder dasselbe sagen soll.

    Ich denke dennoch, dass es hilfreich ist das logische Modell aufzuzeichnen, sprich wie ich es angedeutet habe. (siehe oben)

    Gegen die Bilder an sich hat Elmar sicher nichts. Lies doch sein Posting nochmal, dann solltest Du auch verstehen, was er meinte.

    Dein Tipp mit dem Manager ist ja ok, kannst Du dennoch mal aufzeichen, wie das logische Modell, welche Klassen man benötigt.

    Lies bitte auch das, was man dir schreibt (auch das vermisse ich bei dir schon seit langem). Alle Antworten stehen in diesem Thread. Du solltest vom Forum nicht erwarten, dass dir alles mundgerecht in genau für dich passenden Häppchen und am besten noch vorgekaut vorgesetzt wird. Ein wenig selbst was tun musst Du schon.

    Von 0->1 Etwas tun und von 1->0 Etwas anders tun.
     
    If e.OldValue = 0 AndAlso e.NewValue = 1 Then
        MachEtwas()
    ElseIf e.OldValue = 1 AndAlso e.NewValue = 0 Then
        MachEtwasAnderes()
    End if

    Die Frage ist damit beantwortet. Aber hilft dir das jetzt? Wenn Du die Zusammenhänge nicht verstehst oder verstehen willst, ist alles, was man dir schreibt, vergebene Liebesmüh. Setz dich daher bitte mit dem, was Du machen willst, auch intensiv auseinander und vor allen Dingen: Lerne.


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community


    Samstag, 6. Oktober 2012 17:32
    Moderator
  •  

    If e.OldValue = 0 AndAlso e.NewValue = 1 Then
        MachEtwas()
    ElseIf e.OldValue = 1 AndAlso e.NewValue = 0 Then
        MachEtwasAnderes()
    End if

    Hallo Stefan,

    ok, d.h. ich muss den int Wert umwandeln in binär.

    Ich muss ja nicht nur eine x-beliebige Änderung ermitteln, sondern eben die 16 Eingänge.

    Danach habe ich eine Liste, Array und für alle 16 Eingänge muss ich das obige machen einen Event, Delegate auslösen.

    Sehe ich es korrekt?

    Grüße Andreas

    public BitChangedEventArgs(int data)
           
    {
               
    this._data = (data & 0xffff);   // max. 16 Bit
           
    }


    Danach eine Liste

        mit OldValue = NewValue

    Samstag, 6. Oktober 2012 17:48
  • Hallo Andreas,

    Du musst keine 16 Eingänge erkennen/behandeln, sondern vergleichen, was sich wo geändert hat. Das erreichst Du ganz sicher nicht mit einem Einzeiler.

    Ich poste dir nachstehend zwei Klassen für die Speicherung und dazu ein Formular. Ist zwar in VB, der Code sollte sich aber problemlos übersetzen lassen. Bevor mich nun einer schlägt: Mir ist bewusst, dass man das besser machen kann, allerdings denke ich, dass man die Komplexität nicht noch mehr erhöhen sollte, sonst wir das hier wahrscheinlich gar nix mehr^^

    Public Class ValueChangedEventArgs
    
        Protected OldBits    As BitArray
        Protected NewBits    As BitArray
    
        Private _OldValue    As Int16
        Private _NewValue    As Int16
        Private _ChangedBits As List( Of BitChangedEventArgs )
    
        Public ReadOnly Property OldValue As Int16
            Get
                Return _OldValue
            End Get
        End Property
    
        Public ReadOnly Property NewValue As Int16
            Get
                Return _NewValue
            End Get
        End Property
    
        Public ReadOnly Property ChangedBits As List( Of BitChangedEventArgs )
            Get
                Return _ChangedBits
            End Get
        End Property
    
        Public Sub New( ByVal OldValue As Int16, ByVal NewValue As Int16 )
    
            Me._OldValue    = OldValue
            Me._NewValue    = NewValue
            Me._ChangedBits = New List(Of BitChangedEventArgs )()
    
            Me.OldBits = New BitArray( BitConverter.GetBytes( OldValue ) )
            Me.NewBits = New BitArray( BitConverter.GetBytes( NewValue ) )
    
            For Counter As Int32 = 0 To Me.OldBits.Count - 1
                Me._ChangedBits.Add( New BitChangedEventArgs( Counter, Me.OldBits( Counter ), Me.NewBits( Counter ) ) )
            Next
    
        End Sub
    
    End Class

    Diese Klasse speichert die Werte zu den gegebenen Zahlen und ermittelt aus altem und neuen Wert dann die jeweiligen Bits.

    Public Class BitChangedEventArgs
    
        Private _Index    As Int32
        Private _OldValue As Boolean
        Private _NewValue As Boolean
        Private _Changed  As Boolean = False
    
        Public ReadOnly Property Index As Int32
            Get
                Return _Index
            End Get
        End Property
    
        Public ReadOnly Property OldValue As Boolean
            Get
                Return _OldValue
            End Get
        End Property
    
        Public ReadOnly Property NewValue As Boolean
            Get
                Return _NewValue
            End Get
        End Property
    
        Public ReadOnly Property Changed As Boolean
            Get
                Return _Changed
            End Get
        End Property
    
        Public Sub New( ByVal Index As Int32, ByVal OldValue As Boolean, ByVal NewValue As Boolean )
    
            Me._Index    = Index
            Me._OldValue = OldValue
            Me._NewValue = NewValue
    
            If _OldValue <> _NewValue Then
                Me._Changed = True
            End if
    
        End Sub
    
    End Class

    Diese Klasse dient nur dazu, die Zustände der einzelnen Bits zu speichern. Eine List( Of ... ) wird hierfür dann in der Klasse ValueChangedEventArgs integriert, dort sind die Werte dann abrufbar.

    Public Class Form1
    
        Protected SavedValue As Int16
    
        Public Event ValueChanged( ByVal sender As Object, ByVal e As ValueChangedEventArgs )
    
        Private Sub Button1_Click( sender As System.Object,  e As System.EventArgs) Handles Button1.Click
    
        Dim NewValue As Int16
    
            Int16.TryParse( Value.Text, NewValue )
    
            If SavedValue <> NewValue Then
                RaiseEvent ValueChanged( Me, New ValueChangedEventArgs( SavedValue, NewValue ) )
                SavedValue = NewValue
            End If
    
        End Sub
    
        Public Sub Form_ValueChanged( ByVal sender As Object, ByVal e As ValueChangedEventArgs ) Handles Me.ValueChanged
    
        Dim Message As String = String.Empty
            For Each Item As BitChangedEventArgs In e.ChangedBits.FindAll( Function( Check ) Check.Changed = True )
                Message &= String.Format( "Bit an Stelle {1} wurde von Wert {2} in Wert {3} geändert{0}", ControlChars.NewLine, Item.Index, IIf( Item.OldValue, "1", "0" ), IIf( Item.NewValue, "1", "0" ) )
            Next
            MessageBox.Show( String.Format( "Alter Integer Wert: {1}{0}Neuer Wert: {2}{0}{0}{3}", ControlChars.NewLine, e.OldValue.ToString(), e.NewValue.ToString(), Message ) )
    
        End Sub

    Leg dir im Testprojekt bitte eine Form "Form1" an und bau dort eine Textbox mit dem Namen "Value" ein. Wenn Du das Testprojekt gestartet hast, gib einfach mal verschiedene Zahlen im Bereich von 0 bis 32767 ein und schau, was dabei herauskommt. Danach setzt Du an für dich interessanten Stellen Breakpoints und schaust dir genauer an, was die einzelnen Codeteile eigentlich tun und vor allem, wie.

    Und in die letzte Schleife, die die Elemente durchläuft, die sich geändert haben, kommt dann deine Abfrage von oben (also prüfen auf alter Wert 0, neuer Wert 1, usw.) mit anschließendem Aufruf deiner eigenen Methoden rein.

    ---

    Und ja, ich weiß, dass ich gerade meinen eigenen Krams von eben übern Haufen geworfen habe :)


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community


    Samstag, 6. Oktober 2012 19:52
    Moderator
  • Hi Andreas,
    Stefans Beispiel ist eine der möglichen Anregungen.
     
    Wenn das höchstwertige Bit als Einzelbit von Bedeutung sein kann, dann sollte als Typ UShort genutzt werden.
     
    Wenn die einzelnen Bits konkreten Sachverhalten fest zugeordnet sind, dann sollte man über die Nutzung einer Aufzählung (enum) nachdenken (mit FlagsAttribute).
     
    Wenn Dir das alle zu kompliziert ist und Du mit dem objektorientierten Ansatz zu viele Probleme hast und jedes Bit nur einzeln auszuwerten ist, dann mache das erst einmal einfach nur prozedural mit 16 if/else Anweisungen. Später kannst Du dann schrittweise das so funktionierende Programm verbessern.
     
    Beim Tipp mit dem Manager habe ich nur den prinzipiellen Algorithmus skizziert. Ob Du das prozedural in einer Klasse oder mit mehreren Klassen machst, ist eine Design-Frage, die Du anhand der weiteren Bedingungen (Weiterentwicklung, Testumgebung, Nachnutzung, Arbeitsteilung beim Projektieren usw.) entscheiden musst. Wesentlich bei SPS-Programierung ist auch das multithreading, damit keine Änderungen der Zustände verlorengehen. Und daraus können sich zusätzlich Bedingungen ableiten, die für eine saubere Beherrschung eine Kapselung in Klassen sinnvoll machen.
     
    --
    Viele Gruesse
    Peter
    Sonntag, 7. Oktober 2012 05:24
  • Hallo Andreas,

    Einspruch: Ich bin ein Freund von Bildern, vorzugsweise ausdrucksstarken, z. B. Impressionisten, Expressionisten uvm.

    Er ist kein Freund von Hardcopies mit der Frage: Siehst Du den Fehler? - was ich umschrieben hatte mit Enthusiasmus vermissen.

    Bei Sätzen wie ok, ich muss den int Wert umwandeln in binär, bleibt mir jedoch die Spucke weg. Zur anscheinend notwendigen Aufklärung:
    Warum benutzen Computer nicht das Dezimalsystem?

    Da Du anscheinend nicht begreifen kannst, das wir hier einen Zwergenaufstand um nichts machen, ein (letztes) Beispiel.

    Ich habe auf das Ereignis verzichtet und dafür die Arbeiter direkt in eine Liste gesteckt. Die Verarbeitung erfolgt in einer (trivialen) Schleife, die ihre Eingaben über IEnumerable bezieht. Alternativ könnte hier ein Stream, eine Queue, eine IProducerConsumer uvm. stehen.

    Was alles nur Brimborium ist, die gesamte Logik steckt in der Zeile:

    int state = (prevState ^ newState) & this.BitMask;

    Und um zu zeigen, das es (binär) so simpel funktioniert gibt es eine auf die Logik reduzierte Version FürAnfänger am Anfang.

    using System;
    using System.Collections.Generic;
    
    namespace ElmarBoye.Samples.Code
    {
        internal static class TestBits
        {
            internal static void Run()
            {
                // beide zusammen
                FürAnfänger();
                RunEngine();
            }
    
            /// <summary>
            /// Führt die Tests für die Bitmasken der unten implementierten WorkerA..C aus.
            /// </summary>
            internal static void FürAnfänger()
            {
                // zweimal je ein Bit, dann beide zusammen (siehe Worker A, B, C)
                var bitMasks = new int[] { 0x1000, 0x0200, 0x1200 }; 
                foreach (var bitmask in bitMasks)
                {
                    Console.WriteLine("Bitmask is {0:X4}", bitmask);
                    FürAnfänger(bitmask);
                }
            }
    
            /// <summary>Binäre Logik für Anfänger oder wie testet man Bits...</summary>
            /// <seealso cref="http://de.wikipedia.org/wiki/Bitweiser_Operator"/>
            private static void FürAnfänger(int bitMask)
            {
                int prevState = 0;
                foreach (int newState in SimpleStateInput())
                {
                    int evalState = (prevState ^ newState) & bitMask;
                    Console.WriteLine("Prev: {0:X4}, New: {1:X4}, Result: {2:X4} ({3})", prevState, newState, evalState, evalState != 0);
                    if (evalState != 0)
                    {
                        prevState = newState & bitMask;
                    }
                }
            }
    
            /// <summary>Startet die Beispiel Engine.</summary>
            internal static void RunEngine()
            {
                var engine = new StatusWorkerEngine();
                engine.Worker.Add(new ConsoleStatusWorker("Worker A", 0x1000));
                engine.Worker.Add(new ConsoleStatusWorker("Worker B", 0x0200));
                engine.Worker.Add(new ConsoleStatusWorker("Worker C", 0x1200));
    
                Func<IEnumerable<int>> input = SimpleStateInput;
                //Func<IEnumerable<int>> input = RandomStateInput;
                engine.Execute(input);
            }
    
            /// <summary>Liefert eine Anzahl von Integern.</summary>
            private static IEnumerable<int> SimpleStateInput()
            {
                // Für Worker A..C 
                int[] states = new int[] { 0x1000, 0x1100, 0x0200, 0x02FF, 0x12FF, 0x1200, 0x1000, 0x00FF };
                
                for (int index = 0; index < states.Length; index++)
                    yield return states[index];
            }
    
            /// <summary>Liefert 1000 Integer.</summary>
            /// <param name="count">Anzahl von Elementen</param>
            private static IEnumerable<int> RandomStateInput()
            {
                int count = 1000;
                var random = new Random();
                while (count > 0)
                {
                    count--;
                    int state = random.Next(0, 0xffff);
                    yield return state;
                }
            }
        }
    
        /// <summary>
        ///  (BASIS)-Klasse für die Verarbeitung anhand von Statusänderungen.
        /// </summary>
        public class StatusWorker
        {
            const int MAXSTATEBITS = 0xffff; // 16-Bit-Word
    
            /// <summary>Name für Ausgaben.</summary>
            public string Name { get; private set; }
            /// <summary>Die zu berücksichtigen Bits (Word).</summary>
            public int BitMask { get; private set; }
            /// <summary>Letzter Status.</summary>
            public int LastState { get; private set; }
    
            /// <summary>Erzeugt einen Worker mit einem Namen und einer BitMask.</summary>
            /// <param name="name"></param>
            /// <param name="bitMask"></param>
            protected StatusWorker(string name, int bitMask)
            {
                this.Name = name ?? String.Empty;
                this.BitMask = (bitMask & MAXSTATEBITS);
            }
    
            /// <summary>Von der Engine aufgerufen.</summary>
            internal void Execute(int state)
            {
                state &= MAXSTATEBITS;
                if (ShouldExecuteState(state))
                {
                    this.ExecuteState(state);
                    this.LastState = (state & this.BitMask);
                }
            }
    
            /// <summary>Testet, ob die Bedingungen zutreffen.</summary>
            protected virtual bool ShouldExecuteState(int state)
            {
                int evalState = GetMaskedState(this.LastState, state);
                return (evalState != 0);
            }
    
            /// <summary>Führt Sinnvolles aus...</summary>
            protected virtual void ExecuteState(int state)
            {
            }
    
            /// <summary>Testet auf BitMask, und der Grund des Unterfangens!</summary>
            protected int GetMaskedState(int prevState, int newState)
            {
                int state = (prevState ^ newState) & this.BitMask;
                return state;
            }
    
            /// <summary>Von der Engine zu Anfang aufgerufen, führt Initialisierungen durch.</summary>
            public virtual void Initialize()
            {
                this.LastState = 0;
            }
    
            /// <summary>Von der Engine am Ende aufgerufen, führt Aufräumarbeiten durch.</summary>
            public virtual void Shutdown()
            {
                this.LastState = -1;
            }
        }
    
        /// <summary>Exemplarische Implemenation für eine Konsolenausgabe.</summary>
        public class ConsoleStatusWorker : StatusWorker
        {
            public ConsoleStatusWorker(string name, int bitMask)
                : base(name, bitMask)
            {
            }
    
            /// <summary>Protokolliert auf Console.</summary>
            protected override bool ShouldExecuteState(int state)
            {
                bool shouldExecute = base.ShouldExecuteState(state);
                Console.WriteLine("\t{0} ShouldExecute: {1:X4} == {2:X4} ({3})", this.Name, this.LastState, state, shouldExecute);
                return shouldExecute;
            }
    
            /// <summary>Führt irgendetwas aus (hier eine Console-Ausgabe)</summary>
            protected override void ExecuteState(int state)
            {
                int newState = GetMaskedState(this.LastState, state);
                Console.WriteLine("\t{0} Execute      : {1:X4} => {2:X4}", this.Name, this.LastState, newState); 
            }
        }
    
        /// <summary>Primitive Engine, die die Arbeit an StatusWorker delegiert.</summary>
        public class StatusWorkerEngine
        {
            public StatusWorkerEngine()
            {
                this.Worker = new List<StatusWorker>();
            }
    
            public List<StatusWorker> Worker { get; private set; }
    
            public void Execute(Func<IEnumerable<int>> input)
            {
                if (input == null)
                    throw new ArgumentException("I need some input!");
    
                // Initialisierung
                foreach (var workerItem in this.Worker)
                    workerItem.Initialize();
    
                // Eingaben an die Worker übergeben
                foreach (int state in input.Invoke())
                {
                    Console.WriteLine("\n***Engine START: {0:X4}", state);
                    
                    foreach (var workerItem in this.Worker)
                        workerItem.Execute(state);
    
                    Console.WriteLine("***Engine END : {0:X4}", state);
                }
    
                // Aufräumen
                foreach (var workerItem in this.Worker)
                    workerItem.Shutdown();
            }
        }
    }

    Damit ist der Thread und das Thema für mich abgeschlossen.
    Weitere Antworten werde ich erst geben, wenn ich substantielle Eigenleistungen auf Deiner Seite erkennen kann.

    Gruß Elmar

    • Bearbeitet Elmar BoyeEditor Sonntag, 7. Oktober 2012 15:45 kursiv ist kursiv, egal was das "Branding" sagt.
    • Als Antwort markiert Andreas Bauer2 Montag, 8. Oktober 2012 10:41
    Sonntag, 7. Oktober 2012 15:41
    Beantworter
  • Leg dir im Testprojekt bitte eine Form "Form1" an und bau dort eine Textbox mit dem Namen "Value" ein. Wenn Du das Testprojekt gestartet hast, gib einfach mal verschiedene Zahlen im Bereich von 0 bis 32767 ein und schau, was dabei herauskommt. Danach setzt Du an für dich interessanten Stellen Breakpoints und schaust dir genauer an, was die einzelnen Codeteile eigentlich tun und vor allem, wie.

    Hallo Stefan,

    passt und Danke.
    Das habe ich verstanden. Man sieht es super und trägt zum Verständnis bei.

    Gehört nicht direkt zu diesem Thread.
    Wenn Du eine bessere Möglichkeit siehst, die Formatierung zu machen, sage ich im Voraus Danke.   Siehe Markierung !!!!!!!!!!!!!

    String Binär mit führenden Nullen
    Grüße Andreas

    protected Int16 SavedValue;
            public event ValueChangedEventHandler ValueChanged;
            public delegate void ValueChangedEventHandler(object sender, GlobalValueChangedEventArgs e);
    
            private void btnBitVariante02_Click(object sender, EventArgs e)
            {
                Int16 NewValue = default(Int16);
    
                Int16.TryParse(txtValueTest.Text, out NewValue);
    
                if (SavedValue != NewValue)
                {
                    if (ValueChanged != null)
                    {
                        ValueChanged(this, new GlobalValueChangedEventArgs(SavedValue, NewValue));
                    }
                    SavedValue = NewValue;
                }
            }
    
            private void Form1_Load(object sender, EventArgs e)
            {
                this.ValueChanged += new ValueChangedEventHandler(Form1_ValueChanged);
            }
    
            void Form1_ValueChanged(object sender, GlobalValueChangedEventArgs e)
            {
                string Message = string.Empty;
                foreach (DetailBitChangedEventArgs Item in e.ChangedBits.FindAll(Check => Check.Changed == true))
                {
                    Message += string.Format("Bit an Stelle {1} wurde von Wert {2} in Wert {3} geändert{0}", ControlChars.NewLine, Item.Index, (Item.OldValue ? "1" : "0"), (Item.NewValue ? "1" : "0"));
                }
    
                //string binaerOldValue = String.Format("{0:d16}", Convert.ToString(e.OldValue, 2));
                //string binaerOldValue = String.Format("{0:d20}", 5); //Convert.ToString(e.OldValue, 2));
                string binaerOldValue = String.Format("{0}", Convert.ToString(e.OldValue, 2));
                string binaerNewValue = String.Format("{0}", Convert.ToString(e.NewValue, 2));
    // !!!!!!! die Markierung !!!!!!!!!!!!!
                string maske = String.Format("{0:d16}", 0);
                string binaerOldValueMessage = maske.Substring(0, (maske.Length - binaerOldValue.Length)) + binaerOldValue;
                string binaerNewValueMessage = maske.Substring(0, (maske.Length - binaerNewValue.Length)) + binaerNewValue;
    
    
    
                MessageBox.Show(string.Format("Alter Integer Wert: {1}\t{4}{0}Neuer Wert: {2}\t\t{5}{0}{0}{3}", ControlChars.NewLine, e.OldValue.ToString(), e.NewValue.ToString(), Message,
                    binaerOldValueMessage, binaerNewValueMessage));
                //throw new NotImplementedException();
            }

    1 von 2

    2 von 2 - pass5t

    Montag, 8. Oktober 2012 10:31

  • Damit ist der Thread und das Thema für mich abgeschlossen.

    Hallo Elmar,

    ist in Ordnung. Selbstverständlich schaue ich mir das genauer jetzt dann an und sage Danke und hoffe nach wie vor auf Deine Unterstützung.

    Es muss irgendwo Konzepte geben. Konzeptvorlagen evtl.

    Das Konzept jetzt von Stefan sagt mir zu und finde es gut.

    Wüsste nicht, was man noch verbessern kann.

    Polling, Änderungen

    Ich kenne die Aufgabe und  muss jetzt schnell und gut zu einer Lösung kommen. Zu einer guten Lösung und nicht try and error.

    Wie Du sagst man muss es auch verstehen.

    Grüße Andreas

    Montag, 8. Oktober 2012 10:41


  • Gehört nicht direkt zu diesem Thread.
    Wenn Du eine bessere Möglichkeit siehst, die Formatierung zu machen, sage ich im Voraus Danke.   Siehe Markierung !!!!!!!!!!!!!

    String Binär mit führenden Nullen



    Hi,
    char pad = '0';
    binaerOldValueMessage = binaerOldValue.PadLeft(16, pad);
    binaerNewValueMessage = binaerNewValue.PadLeft(16, pad);
    MSDN

    Hope to help, Oliver

    Dienstag, 9. Oktober 2012 10:04