Benutzer mit den meisten Antworten
Bitänderung - Event auslösen - Konzept

Frage
-
Hallo,
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
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
- Bearbeitet Stefan FalzModerator Samstag, 6. Oktober 2012 19:56
- Als Antwort markiert Andreas Bauer2 Montag, 8. Oktober 2012 10:33
-
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
-
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- Als Antwort markiert Andreas Bauer2 Dienstag, 9. Oktober 2012 17:38
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.aspxOder 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/
- 8 Bits ergeben 1 Byte. Nur um das zu 101% sicher zu stellen ;)
-
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
-
- Wovon soll das 12. Bit gesetzt sein?
Hallo Koopakiller,
in C#
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?
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; }
- Bearbeitet Andreas Bauer2 Freitag, 5. Oktober 2012 09:11 Format
-
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
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
-
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
-
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
-
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).
-
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
-
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
-
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
-
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 -
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
-
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
- Bearbeitet Stefan FalzModerator Samstag, 6. Oktober 2012 17:32
-
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 Listemit OldValue = NewValue
-
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
- Bearbeitet Stefan FalzModerator Samstag, 6. Oktober 2012 19:56
- Als Antwort markiert Andreas Bauer2 Montag, 8. Oktober 2012 10:33
-
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 -
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
-
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 Andreasprotected 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(); }
-
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.
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
-
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- Als Antwort markiert Andreas Bauer2 Dienstag, 9. Oktober 2012 17:38