Laden...
N
Neals myCSharp.de - Member
Ingenieur Nordseeküste Dabei seit 03.04.2008 203 Beiträge
Benutzerbeschreibung

Forenbeiträge von Neals Ingesamt 203 Beiträge

18.02.2011 - 16:28 Uhr

Vlcht helfen dir die Attribute [StructLayout(LayoutKind.Sequential, Pack=1)] und [MarshalAs(UnmanagedType.ByValArray , SizeConst = 2)] weiter. Damit kann die Struktur des Datentyps im Speicher festgelegt werden und dann könnte man vlcht mit mem-copy oder so arbeiten.

16.01.2011 - 12:28 Uhr

Hier die Sourcen...

16.01.2011 - 12:27 Uhr

Beschreibung:

Dieses kleine Tool bietet die Möglichkeit Informationen über das System mit Hilfe der WMI (Windows Management Instrumentation) auszulesen. Es wird eine Auflistung der Komponenten angezeigt, von der dann eine ausgewählt und angezeigt werden kann. Die WMI ist eine Erweiterung des CIM (Common Information Models) und wird zur Administration und Fernwartung von Windows-Systemen verwendet.

Weitere Informationen:
Wikipedia: WMI
MSDN: WMI


namespace WmiReader
{
    public class Wmi
    {
        public string Read(string item)
        {
            var builder = new StringBuilder();

            try
            {
                using (var management = new ManagementClass(item))
                {
                    using (var collection = management.GetInstances())
                    {
                        if (collection.Count > 0)
                        {
                            builder.AppendLine(string.Format("{0}", item));
                            WriteManagementObjects(builder, collection);
                        }
                        else
                        {
                            builder.AppendLine("Not Items found!");
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                builder.AppendLine("Exception occured!");
                builder.AppendLine(string.Format("{0}: {1}", ex, ex.Message));
            }

            return builder.ToString();
        }

        private static void WriteManagementObjects(StringBuilder builder, ManagementObjectCollection collection)
        {
            if (builder == null)
            {
                return;
            }

            if (collection == null)
            {
                return;
            }

            var counter = 1;

            foreach (ManagementObject obj in collection)
            {
                builder.AppendLine(string.Format("\t{0}", counter++));

                builder.AppendLine(string.Format("\t\tProperties:"));

                foreach (var data in obj.Properties)
                {
                    WritePropertyData(builder, data);
                }

                builder.AppendLine(string.Format("\t\tSystemProperties:"));

                foreach (var data in obj.SystemProperties)
                {
                    WritePropertyData(builder, data);
                }
            }
        }

        private static void WritePropertyData(StringBuilder builder, PropertyData data)
        {
            if (builder == null)
            {
                return;
            }

            if (data == null)
            {
                return;
            }

            if (data.Value != null)
            {
                builder.AppendLine(string.Format("\t\t\t{0}: {1}", data.Name, data.Value));
            }
        }

        public static List<string> Win32Classes = new List<string>
        {
            "Win32_Account",
            "Win32_BIOS",
            "Win32_BootConfiguration",
            "Win32_Bus",
            "Win32_CacheMemory",
            "Win32_CDROMDrive",
            "Win32_ComputerShutdownEvent",
            "Win32_ComputerSystem",
            "Win32_ComputerSystemProcessor",
            "Win32_ComputerSystemProduct",
            "Win32_ComputerSystemWindowsProductActivationSetting",
            // ... Komplette Liste im Anhang zu finden.
        };
    }
}

Schlagwörter: WMI, CIM, Windows, System, Informationen

15.01.2011 - 17:28 Uhr

Habe mal einen WMI-Reader gebastelt, der ließt alles mögliche aus.

Habe Ihn, wie gewünscht in den Snipptes-Bereich gepostet.
WMI-Reader

20.10.2010 - 18:20 Uhr

Anstatt dem SynchronizationContext erstellst du dir einfach ein leeres Control im MainThread. Jetzt kannst du über Control.InvokeRequired prüfen ob du invoken musst und dann ggf. über Control.Invoke oder Control.BeginInvoke den Aufruf in den MainThread verschieben.

11.10.2010 - 13:36 Uhr

Stichwörter: Wireshark WinPcap

Findest auch Beispiele bei CodeProject

05.10.2010 - 17:40 Uhr

Ok, versuche gerade die Wurzel zu packen...

Entwickle gerade ein kleiens Tool, welches einen TCP-Socket nutzt.
Da wollte ich gleich mal das neue Async-Pattern von MS und EBC verwenden.

Habe im Anhang den ersten Code. Wäre nett, wenn Ihr ein bisschen Feedback geben könntet, ob auch alles im Sinne von EBC ist.

    public class ServerPlatine
    {
        public IInputPin<bool> InListen { get; private set; }

        public IInputPin<bool> InClose { get; private set; }

        public IOutputPin<string> OutInfos { get; private set; }

        // --------------------------------------------------

        private readonly ServerSocket _socket;

        public ServerPlatine()
        {
            _socket = new ServerSocket(new IPEndPoint(IPAddress.Any, 50000));

            InListen = new InputPin<bool>(DoListen);
            InClose = new InputPin<bool>(DoClose);
            OutInfos = new OutputPin<string>();

            _socket.OutAccept.Subscribe(OnAccept, OnError);
        }

        private void Write(string infos)
        {
            OutInfos.Post(infos);
        }

        private void OnError(Exception error)
        {
            Write(string.Concat(error.Message, "\r\n", error.StackTrace));
        }

        private void OnAccept(AcceptArgs args)
        {
            Write("OnAccept");

            ClientSocket socket = args.Socket;

            socket.InReceive.OnPost(true);

            socket.OutReceive.Subscribe(OnReceive, OnError);
        }

        private void OnReceive(ReceiveArgs args)
        {
            Write("OnReceive");

            string received = Encoding.ASCII.GetString(args.Buffer).Replace("\0", string.Empty).Trim();

            Console.WriteLine(string.Concat("OnReceive: ", received));
            
            args.Socket.InSend.OnPost(new SendArgs(Encoding.ASCII.GetBytes("Hello Client!"), OnSend));
        }

        private void OnSend()
        {
            Write("OnSend");
        }

        private void DoClose(bool value)
        {
            _socket.InClose.OnPost(new CloseArgs());
        }

        private void DoListen(bool value)
        {
            _socket.InListen.OnPost(new ListenArgs());
        }
    }
01.10.2010 - 10:39 Uhr

Hey Ralf, da du ja der Spezi auf dem Gebiet EBC bist, frag ich einfach mal nach:
Ich spiele auch gerade mit EBC rum und versuche mir zur Erleichterung ein kleines Framework aufzubauen.

Dafür Definitionen:
Provider stellt Funktionen zur Verfügung.

public interface IProvider<in TRequest, TResponse>
{
    void InRequest(TRequest request);
    event Action<TResponse> OutResponse;
    void DoResponse(TResponse response);
}

Consumer nimmt eine Funktion in Anspruch.

public interface IConsumer<TRequest, in TResponse>
{
    void DoRequest(TRequest request);
    event Action<TRequest> OutRequest;
    void InResponse(TResponse response);
}

Dazu Standard-Implementierungen:

public class Provider<TRequest, TResponse> : IProvider<TRequest, TResponse>
{
    private readonly Action<TRequest> _indication;

    public Provider(Action<TRequest> indication)
    {
        _indication = indication;
    }

    public event Action<TResponse> OutResponse;

    public void InRequest(TRequest request)
    {
        if(_indication != null) _indication(request);
    }

    public void DoResponse(TResponse response)
    {
        // Hier z.B. Aufruf in ThreadPool verschieben -> AsyncProvider
        if(OutResponse != null) OutResponse(response);
    }
}
public class Consumer<TRequest, TResponse> : IConsumer<TRequest, TResponse>
{
    private readonly Action<TResponse> _confirmation;

    public Consumer(Action<TResponse> confirmation)
    {
        _confirmation = confirmation;
    }

    public void DoRequest(TRequest request)
    {
        // Hier z.B. Aufruf in ThreadPool verschieben -> AsyncConsumer
        if(OutRequest!= null) OutRequest(request);
    }

    public event Action<TRequest> OutRequest;

    public void InResponse(TResponse response)
    {
        if(_confirmation!= null) _confirmation(response);
    }
}

Über die Interfaces kann ich einfach Binden:

public class Binder<TRequest, TResponse>
{
    public static void Bind(IConsumer<TRequest, TResponse> consumer, IProvider<TRequest, TResponse> provider)
    {
        consumer.OutRequest += provider.InRequest;
        provider.OutResponse += consumer.InResponse;
    }
}

Soweit so gut... oder gibts Anmerkungen, Vorschläge?? Raus damit!

Aber ein Repository ist halt ein Akteur, eine Ressource. Die dient wahrscheinlich vielen Clients. Wenn du dann einen Out_Load Event hast, dann kannst du den aber eigentlich nur an einen Empfänger binden.

Falls also viele Clients etwas vom Repo wollen, dann musst du einen Request zum Laden schicken, der einen ad hoc Antwort-Pin enthält, ...

Für solche Fälle, weiß ich jedoch immoment noch keine einfache Lösung. Dann müsste ich dem Request-Typen immer ein Callback (Action-Delegate) mitgeben, die an die Response übergeben und dann vom Consumer aufrufen lassen.

30.09.2010 - 20:26 Uhr
public class Repository : IRepository
{
    public void In_Load()
    {
        string data = string.Empty;

        // Lade Daten ...
        data = "bla";

        Out_Loaded(data);
    }

    public event Action<string> Out_Loaded;
}
public class Consumer
{
    public Action Out_Load;

    public void In_Loaded(string data)
    {
        Console.WriteLine(data);
    }

    public void Run()
    {
        Out_Load();
    }
}
public class Test
{
    public void main()
    {
        IRepository rep = new Repository();
        Consumer con = new Consumer();

        rep.Out_Loaded += con.In_Loaded;
        con.Out_Load += rep.In_Load;

        con.Run(); // "bla" wird geschrieben.
}

Ich hoffe, ich habe das Beispiel korrekt getippt.
Consumer liest die Daten aus, indem er Out_Load aufruft. Der Aufruf wird an das In_Load vom Repository weitergeleitet. Das Repository ließt die Daten aus und gibt das Ergebnis über Out_Loaded zurück. Das Ergebniss wird an den Consumer über In_Loaded weitergegeben und auf die Console geschrieben.

30.09.2010 - 17:43 Uhr

Deine Load-Anfrage ist eine Funktion, der Rückgabewert wird über ein Event ausgegeben:

public interface IRepository
{
    void In_Load();
    Action<string> Out_Load;
}

Vlcht hilft dir diese Bild:

16.09.2010 - 14:08 Uhr

Ich würde mit den BeginX-Methoden der Socket-Klasse arbeiten. Diese sind bereits optimiert, verwenden den ThreadPool und reagieren auf Events, welche direkt aus den Hardware-Treibern resultieren.

19.06.2010 - 12:22 Uhr

Ich sehe bei deinem Ansatz absolut keinen Unterschied zu dem von gfoidl und sehe die gleichen Nachteile: Abhängigkeiten

Der Unterschied: Es ist in der Response enthalten, ob eine Exception aufgetreten ist.

Abhängigkeiten: Die Komponente ist nur Abhängig von der Response und erfährt darin, ob ein Fehler aufgetreten ist.

Die Komponente, welche die Anfrage stellt, erhält auch die Antwort und ggf. eine Fehlermeldung auf die Anfrage. Ganz abstrakt, stelle ich jemanden eine Frage und erhalte eine Antwort. Diese Antwort kann aber auch "Weiß ich nicht!" lauten.

Der MessageBroker müsste dann ja an die anfragende Komponente, im Falle einer Exception, irgendeine Antwort senden. In dieser Antwort muss dann auch iregndeine Meldung enthalten sein, das ein Fehler aufgetreten ist und die enthaltenen Daten nicht verwendet werden sollen.

19.06.2010 - 11:44 Uhr

Ich habe den Vorteil von EBC's gerade bei dem Aufbau von Kommunikations-Schnittstellen für mich entdeckt.

Eine solche Schnittstelle hat 'Input'-Pins, welche ich als Request bezeichne und 'Output'-Pins, welche ich als Response bezeichne. Eben klassisch aus der Denke der Kommunikation herraus. Wenn ich als Nutzer der Schnittstelle nun einen Request sende erwarte ich einen Response mit den angefragten Daten. Wenn auf dem externen System ein Fehler auftritt und es kommt kein Response zurück, ist der Nutzer unwissen und kann darauf nicht reagieren. Daher sende ich ein Response, der die Exception enthält. So kann der Nutzer, der die Daten anfragt entscheiden, wie er darauf reagiert. Ob er es ignoriert oder eine zweite Anfrage los sendet.

Umgesetzt habe ich das mit einer Basisklasse zu diesen Requests:

public class ResponseBase : IResponse
{
    private readonly Exception _exception;

    protected ResponseBase()
    {
        _exception = null;
    }

    protected ResponseBase(Exception exception)
    {
        _exception = exception;
    }

    public Exception Exception
    {
        get
        {
            return _exception;
        }
    }

    public void Throw()
    {
        if(_exception != null)
        {
            throw _exception;
        }
    }
}

In der Schnittstelle wird nun entweder das Event mit der Korrekten Response gefeuert, oder die Response mit der enthaltenen Exception.

FireResponse(new Response(new NotFoundException()));

Der Nutzer wartet auf die Response und ruft bei Eintreffen als erstes die Throw-Methode auf um auf eventuelle Fehler zu reagieren.

OnResponse(Response response)
{
    try
    {
        response.Throw()
    }
    catch(NotFoundException ex)
    {
        // Auf Exception reagieren
        return;
    }

    response.Data; // Normale Abarbeitung
}

Bin immoment noch am überlegen, sogar nach dem senden des Request's einen Timer zu starten. Wenn der Timer abläuft und die Response noch nicht eingetroffen ist, wird ein Timeout gefeuert.

29.05.2010 - 11:55 Uhr

Der Schlüssel ist, das der Thread nicht durchgehend in der Schleife läuft!
Stattdessen wird über Monitor.Wait und Monitor.Pulse die Abarbeitung des Threads gestartet und gestoppt. Die Verwendung kannst dir am Beispiel der JobQueue ansehen.

// Thread
while(_run)
{
    DoWork(); // Abarbeitung

    lock(this)
        Monitor.Wait(this); // Auf nächste Nachricht warten
}

Wenn ein Packet eintrifft mit Monitor.Pulse den Thread wieder starten.

29.05.2010 - 11:40 Uhr

Das mache ich einfach mittels einer leeren while (true) Schleife.
Vielleicht ist das schlecht?

Du hast das Problem doch schon selbst erkannt! Jetzt musst du es nurnoch beheben.
Schau dir mal die JobQueue von herb an, vielleicht hilft dir das weiter.

23.05.2010 - 15:20 Uhr

Habe von mehreren Seiten gehört, das lock(this) nicht verwendet werden sollten. Denn den Code, den du gepostet hast, kann auch ganz schnell zu einem Deadlock werden. Wenn Beispielsweise lock(list) { list.Add(x); } und im Add wiederrum lock(this) { _list.Add(x) } genutzt wird.

Ok, sehe den Deadlock zwar immoment nicht, aber werde dann wohl beim Iterate bleiben. Danke dir.

23.05.2010 - 14:15 Uhr

Threadsafe List<T> von dieser Art:

public class SyncList<T> : IList<T>
{
    private readonly object _sync;

    private readonly IList<T> _list;

    public SyncList() : this(new List<T>()) { }

    public SyncList(int capacity) : this(new List<T>(capacity)) { }

    public SyncList(IList<T> list)
    {
        _sync = new object();
        _list = list;
    }

    public void Add(T item)
    {
        lock (_sync)
        {
            _list.Add(item);
        }
    }

    public bool Remove(T item)
    {
        lock (_sync)
        {
            return _list.Remove(item);
        }
    }
}

Alle zugriffe werden über lock(_sync) synchronisiert. Probleme habe ich aber immer wenn über die Liste iteriert werden soll, denn folgendes Konstrukt ist nicht sicher:


public IEnumerator<T> GetEnumerator()
{
    lock(_sync)
    {
        return _list.GetEnumerator();
    }
}

Stattdessen habe ich bissher immer über die folgende Funktion iteriert:

public void Iterate(Action<T> action)
{
    lock (_sync)
    {
        foreach (T value in _list)
        {
            action(value);
        }
    }
}

Damit erschlagen sicher aber noch nicht alle Anwendungsfälle und ich müsste mehrere Überladungen schreiben. Da kam mir folgende Funktion in den Sinn, die über yield return die Enumeration zurückgibt. Ist das threadsafe?


public IEnumerator<T> GetEnumerator()
{
    lock(_sync)
    {
        foreach(T item in _list)
        {
            yield return item;
        }
    }
}
04.05.2010 - 11:33 Uhr

Load ist wohl ein Event, welches mit += abboniert wird.

Der Term dahinter ist ein "anonymer Delegate".
Unter dem Stickwort solltest du genug finden.

Kurz gesagt, wird einfach eine Methode erzeugt, die die Operationen in den geschweiften Klammern ausführt, sobald das Event gefeuert wird.

01.05.2010 - 13:58 Uhr

dafür verwendet man in der regel einen konkreten typen (also Action<object,MyEventArgs> z.B.). im übrigen verwendet man hierfür auch eher die bereits vorhanden delegaten Action<T> (und allen seinen "überladungen") oder wenn es mit rückgabe sein soll Func<T,TResult> (und allen seinen "überladungen").

Auch wenn ich mein Callback durch Action<T> ersetze, habe ich immernoch einen generischen Delegaten. Wenn ich EventArgs verwende, müssten diese ja auch wieder generisch sein. Damit drehe ich mich im Kreis.

und nochmals im übrigen riecht das was du da machst nach observerpattern. wegen dem .Add... nehme ich mal an das sich mehrere registrieren können und das wiederrum ist in .net bequemer und einheitlicher über events zu lösen.

Ja, aber der Callback ist ja abhängig von der Variablen, auf den die "Notification" angelegt wird.

Denke es ist für den Verwender der Klasse angenehmer einen Callback zu übergeben, als ein Event zu abonnieren und dann jedes mal zu prüfen, ob das Event überhaupt für mich gedacht ist. Also den variableName prüfen. Ausserdem entsteht bei mehreren hundert Abonnenten ein gewisser Overhead, der vermieden werden kann.

30.04.2010 - 07:21 Uhr

Ich habe eine Kommunikationsschnittstelle, der ich ein Objekt als Handle übergeben kann. Darin übergebe ich den Callback, der beim Eintreffen des Telegrams ausgeführt werden soll.

public int AddNotify(string variableName, NotifyCallback callback, int cycleTime)
        {
            try
            {
                MonitoredItem monitoredItem = new MonitoredItem(_subscription.DefaultItem);

                NodeId tempNodeId = new NodeId(variableName, plcNameSpace);

                //.......
                monitoredItem.Handle = callback; // Hier caste ich den Callback in ein Objekt.

                _subscription.AddItem(monitoredItem);

                _subscription.ApplyChanges();

                return (int)monitoredItem.ClientHandle;
            }
            catch (Exception)
            {
                throw; //....
            }
        }

private void OnNotification(Session session, NotificationEventArgs e)
        {
            NotificationMessage message = e.NotificationMessage;

            foreach (MonitoredItemNotification datachange in message.GetDataChanges(false))
            {
                try
                {
                    MonitoredItem monitoredItem = e.Subscription.FindItemByClientHandle(datachange.ClientHandle);

                    if (monitoredItem == null)
                    {
                        continue;
                    }

                    if (monitoredItem.Handle is NotifyCallback)
                    {
                        NotifyCallback callback = monitoredItem.Handle as NotifyCallback; // Hier möchte ich zurück casten
                    }
                    else
                    {
                        throw new Exception("Unknown handle!");
                    }

                    if (callback != null)
                    {
                        callback(datachange.Value.Value)); // Hier möchte ich ausführen
                    }
                }
                catch (Exception)
                {
                    throw; //....
                }
            }
        }

Ist viel Code geworden, um ne Kleinigkeit darzustellen 😉

Mein Ziel ist aber eigentlich:

public in AddNotify<T>(string variableName, NotifyCallback<T> callback, int cycleTime)
29.04.2010 - 22:19 Uhr

Hallo,

ich habe einen generischen Delegate

public delegate void MyDelegate<T>(T data);

den ich in ein Object caste.

Jetzt erhalte ich diesen Delegate als Object wieder. Gibt es eine Möglichkeit, herrauszufinden, welchen Typen dieser Delegate verwendet? Oder gibt es eine Möglichkeit diesen Delegate jetzt auszuführen?

28.04.2010 - 18:49 Uhr

Wenn ich dich richtig verstanden habe, möchstest du sowas bauen: Smart Thread Pool

27.04.2010 - 19:26 Uhr

MD5 ist ein Hashing-Verfahren, das ist nicht dazu gedacht, es wieder zu entschlüsseln.

EDIT: Mal davon abgesehen, dass ich in deinem Code nicht nachvollziehen kann, wie du verschlüsselst. Schreibst den Text nur als Byte-Wurst in eine Datei...

21.04.2010 - 11:03 Uhr

Die werden sie nicht so einfach Kündigen können. Dafür müssten sie ihr erst mehrere Abmahnungen erteilen.

Kündigungschutz für Auszubildende ist ziemlich stark und nicht so einfach zu umgehen.

KÜNDIGUNG NACH ABLAUF DER PROBEZEIT
Völlig anders verhält sich die Rechtslage nach Ablauf der Probezeit. Hier ist zunächst zu differenzieren, ob der Auszubildende oder der Ausbildungsbetrieb kündigt. Während der Auszubildende auch nach Ablauf der Probezeit das Ausbildungsverhältnis mit einer Kündigungsfrist von vier Wochen kündigen kann, wenn er etwa die Berufsausbildung aufgeben oder sich für eine andere Berufstätigkeit ausbilden lassen will, kann der Ausbildungsbetrieb den Vertrag nur noch aus wichtigem Grund und damit fristlos kündigen. Nach der Rechtsprechung werden an diesen wichtigen Grund im Sinne des BBiG sehr strenge Anforderungen geknüpft.

Normale Pflichtverletzungen oder Nachlässigkeiten wie zum Beispiel Zuspätkommen reichen nicht aus. Es müssen vielmehr Umstände vorliegen, die es dem Ausbildungsbetrieb unzumutbar machen, das Ausbildungsverhältnis bis zur vorgesehenen Beendigung fortzusetzen. Von der Rechtsprechung ist dabei insbesondere anerkannt, dass Fälle des Diebstahles von Firmeneigentum oder die Ohrfeige oder Beleidigung des Ausbilders einen solchen wichtigen Grund darstellen. Zu beachten ist hier jedoch, dass im Wege der Interessenabwägung auf Seiten des Auszubildenden insbesondere die Dauer des Ausbildungsverhältnisses, das jugendliche Alter und die geistige Reife des Auszubildenden berücksichtigt werden müssen. Insbesondere dann, wenn sich das Ausbildungsverhältnis bereits im fortgeschrittenen Stadium, zum Beispiel im dritten Ausbildungsjahr befindet, stellt die Rechtsprechung außerordentlich hohe Anforderungen an den erforderlichen wichtigen Grund.

15.04.2010 - 08:00 Uhr

Ich bin auch mit meinen 23 Jahren begeisterter Leser der "Coding for Fun"-Reihe. Denke das könnten auch interessante Bücher für dich sein.

http://www.amazon.de/Coding-Fun-Programmieren-spielen-Geschichte/dp/3836211165

03.04.2010 - 09:39 Uhr

Dann muss man auchnoch die ganzen Shortcuts abfangen, wie STRG-ALT-ENTF oder ALT-TAB. Ich habs mal so umgesetzt, das ich im Hintergrund den Explorer abschieße. Dann hatt der Anwender keine Möglichkeit mehr, darauf zuzugreifen.

30.03.2010 - 07:45 Uhr

Oder du nimmst einfach ne XML-Datei, die du über Serialisierung einließt/speicherst. Dann kannst du recht einfach und schnell deine Applikation über die XML-Datei anpassen.

@soma:
Naja, was meinst du mit Beckhoff? ADS, OPC, OPC UA, MODBUS ... hängt ja letztlich von dem Protokoll ab.

17.03.2010 - 07:23 Uhr

Win + L

also Windows-Taste + L drücken und ausloggen. Das hat geholfen 😉

23.02.2010 - 10:55 Uhr

Das Auslesen und Beschreiben von bool'schen Variablen sind sogenannte atomare Operationen. Daher musst du Zugriffe auf Bool nicht synchronisieren. Damit aber eine CPU nicht einen zwischengespeicherten Wert des Bools verwendet, der eventuell veraltet ist, wird volatile angegeben. Damit wird bei jedem Aufruf der aktuelle Wert verwendet.

19.02.2010 - 17:38 Uhr

Ohne die 20-Tausend Zeilen Code gelesen zu haben, würd ich dir mal empfehlen, hier rein zu schauen: SyncQueue <T> - Eine praktische Job-Queue

19.02.2010 - 07:45 Uhr

Naja, Interfaces machen schon sinn, gerade weil du viele verschiedene Bus-Systeme haben kannst. Versuche dir auch mal, das ein wenig zu verdeutlichen.

Nehmen wir mal an du hast eine Steuerungs-Klasse (typ. SPS) welche über IFeldBus auf dein Bus-System zugreift. Damit weiß die Steuerung nicht, welches Bus-System es benutzt, es kennt nur die Schnittstelle IFeldBus.

Der Kunde benutzt ProfiBus, daher nutztdu die Klasse ProfiBus, welche IFeldBus implementiert. Wenn der Kunde jetzt aber auf CAN-Bus umstellen will, kannst du einfach eine Klasse CanBus schreiben, welche auf IFeldBus implementiert und diese der Steuerungklasse zur Verwendung geben.

Wenn du jetzt eine konkrete Klasse implementiert hättest, müsstest du die Steuerungs-Klasse auch komplett anpassen. Da die Steuerungs-Klasse aber nur IFeldBus kennt und nicht über das Bus-System dahinter weiß, muss du nichts anpassen.

14.02.2010 - 23:30 Uhr

D.h. wenn man eine Klasse hat, die irgendwelche Event-Handler abboniert hat, sollte man IDisposable implementieren und in der Dispose-Methode den Event-Handler wieder entfernen.

Zum einen das, zum anderen sollte man im Dispose einer Klasse, die Events anbietet, die angehängten Delegates nullen.

Um das zu konkretisieren:

EventHandler entfernen wäre...

public MyClass(EventClass eventClass)
{
    eventClass.Click += OnClick;
}

protected virtual void Dispose(bool disposing)
{
    if (disposing)
    {
        eventClass.Click -= OnClick;
    }
}

Und angehängte Delegates nullen wäre...

 public EventHandler<MyEventArgs> MyEvent;

protected virtual void Dispose(bool disposing)
{
    if (dipsosing)
    {
        MyEvent = null;
    }
}

Liege ich da richtig?

[EDIT]Anmerkung von herbivore nachgetragen[/EDIT]

14.02.2010 - 12:51 Uhr

In der Konsolen-Anwendung geht es genauso wie in der Forms-Anwendung. Basieren beide auf dem .Net-Framework und können beide die Management-Funktionen aufrufen.

14.02.2010 - 12:46 Uhr

Nimmst dir die normale Textbox, leitest davon ab und überschreibst OnPaint

OnPaint( .... )
{
    base.OnPaint( ... );

    // Hier dein Dreieck zeichnen
}
03.02.2010 - 17:11 Uhr

Was ist wenn du in deinem Control einfach eine Methode zur verfügung stellst, welche er überschreibt? Im OnPaint rufst du dann diese Methode auf.

public class MyControl : Control
{
    private override OnPaint(PaintEventArgs e)
    {
        ExternalPaint(e.Graphics);
    }

    private virtual void ExternalPaint(Graphics g)
    {
        return;
    }
}

Dann kann später jemand von dem Control erben und einfach das ExternalPaint überschreiben.

02.02.2010 - 10:57 Uhr

Wäre ein synchronisiertes Dictionary nicht einfacher?

 public class SyncDictionary<TKey, TValue> : IDictionary<TKey, TValue>
    {
        private object _sync;
        private IDictionary<TKey, TValue> _dictionary;

        public SyncDictionary() : this(new Dictionary<TKey, TValue>()) { }

        public SyncDictionary(IDictionary<TKey, TValue> dictionary)
        {
            _sync = new object();
            _dictionary = dictionary;
        }

        public void Add(TKey key, TValue value)
        {
            lock (_sync)
            {
                _dictionary.Add(key, value);
            }
        }

        public bool Remove(TKey key)
        {
            lock (_sync)
            {
                return Remove(key);
            }
        }

        public TValue this[TKey key]
        {
            get
            {
                lock (_sync)
                {
                    return _dictionary[key];
                }
            }
            set
            {
                lock (_sync)
                {
                    _dictionary[key] = value;
                }
            }
        }
// ... ... ...
    }

Dann würde das Dictionary nur bei einem Zugriff gesperrt werden und nicht wärend der kompletten Abarbeitung.

29.01.2010 - 17:03 Uhr

Danke für deine Anregungen! Werde deine Vorschläge überdenken und meine Klasse danach überarbeiten.

Was mir direkt dazu einfällt.

Die Berechung der WaitTime verstehe ich nicht.

Ich nehme die Zeit, die die Abarbeitung gebraucht hat und ziehe diese Zeit von der Zykluszeit ab.

Im Dispose machst du einen Pulse ohne lock. Neulich hattest du noch selbst geschrieben, dass das nicht geht:
>
.

Ich rufe meine Funktion Pulse auf, in der wird der lock + Pulse aufgerufen. Das wär ja gut von mir, andere anzumeckern wenn ich's selbst nicht richtig mache. 😉

Deklaration vom WorkItem vergessen:

    public interface IWorkItem
    {
        void Do();
    }

Da kann ich ja beliebige Funktion + Daten drin speichern:

public class ActionItem<T> : IWorkItem
    {
        private Action<T> _action;
        private T _arg;

        public ActionItem(Action<T> action, T arg)
        {
            _action = action;
            _arg = arg;
        }

        public void Do()
        {
            _action(_arg);
        }
    }
29.01.2010 - 16:20 Uhr

Und wie baue ich da das warten/pulse ein?

PS an herbivore:
Die Antwort kenn ich irgendwie. g
Will ja aber nicht nur fertige Sachen verwenden, sondern auch mal selbst was basteln.

29.01.2010 - 15:39 Uhr
    public class CyclicWorkThread : IDisposable
    {
        private Thread _thread;
        private IWorkItem _action;
        private volatile bool _run;
        private string _name;
        private TimeSpan _cycle;
        private object _sync;

        public CyclicWorkThread(string name, IWorkItem action, TimeSpan cycle)
        {
            _name = name;
            _action = action;
            _cycle = cycle;
            _sync = new object();
        }

        private void Work()
        {
            while(_run)
            {
                DateTime start = DateTime.Now;
                
                _action.Do();
                
                lock(_sync)
                {
                    Monitor.Wait(_sync, WaitTime(start));
                }
            }
        }

        private TimeSpan WaitTime(DateTime start)
        {
            return _cycle.Subtract(DateTime.Now.Subtract(start));
        }

        public void Start()
        {
            _run = true;

            lock(_sync)
            {
                if (_thread == null || _thread.ThreadState == ThreadState.Stopped)
                {
                    _thread = new Thread(Work) { Name = _name };
                }
                if (!_thread.IsAlive && _thread.ThreadState != ThreadState.Stopped)
                {
                    _thread.Start();
                }
            }
        }

        public bool Running
        {
            get
            {
                return _run
                       && _thread != null
                       && _thread.IsAlive
                       && _thread.ThreadState != ThreadState.Stopped;
            }
        }

        public void Stop()
        {
            _run = false;
        }

        public void Pulse()
        {
            lock(_sync)
            {
                Monitor.Pulse(_sync);
            }
        }

        public void Change(TimeSpan cycle)
        {
            lock(_sync)
            {
                _cycle = cycle;
            }
        }

        public void Dispose()
        {
            DoDispose(true);
            GC.SuppressFinalize(this);
        }

        ~CyclicWorkThread()
        {
            DoDispose(false);
        }

        private void DoDispose(bool disposing)
        {
            _run = false;

            if(disposing)
            {
                Pulse();
            }

            _thread = null;
        }
    }

Ich möchte einen Thread ne Aufgabe zuweisen, die aber nicht durchweg abgearbeitet wird. Die Aufgabe soll in gewissen Abständen abgearbeitet werden. Trotzdem will ich zu bestimmten Zeitpunkten die Abarbeitung anstoßen können.

Ich benutze nicht den System.Threading.Timer, da ich keinen Thread aus dem Pool nutzen und die Möglichkeit haben möchte, auf die Abarbeitung einzuwirken (Pulse).

Was haltet ihr davon?

28.01.2010 - 17:01 Uhr
_label.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
28.01.2010 - 14:58 Uhr

Du kannst doch einen Reflector benutzen und dir ansehen, was der Compiler da "optimiert" hat.

28.01.2010 - 10:39 Uhr

[EDIT=herbivore]Abgeteilt von Nur gegen Schnittstelle programmieren / Abhängigkeit zur konkreten Klasse vollständig vermeiden. Bitte keine laufenden fremden Threads kapern.[EDIT]

Ich habe da auch mal eine Frage:

Einsatz eines Microkernels am Beispiel einer 3-Schichten-Architektur:

IDataAccess {...}
IBusiness {...}
IPresentation {...}

Dazu die implementierungen:

MyDataAccess : IDataAccess {...}
MyBusiness : IBusiness {...}
MyPresentation : IPresentation {...}

Dem Microkernel würde ich zum Interface jeweils die Implementierung zuweisen und über einen Aufruf wie folgt meine Instanz erzeugen:

IPresentation presentation = Microkernel.Create<IPresentation>();

Das Presentation-Layer greift ja jetzt auf das Business-Layer zu. Wie erhält die Implementierung des Interfaces nun die Referenz auf die Instanz des Business-Layers?
Da ich einen Konstruktor ohne Parameter einsetze, würde ich dann einfach im Konstruktor über den Microkernel mir meine Business-Instanz erzeugen?

class MyPresentation
{
    private IBusiness _business;

    public MyPresentation()
    {
        _business = Microkernel.Create<IBusiness>();
    }
}

Das entspricht dann aber irgendwie nicht dem Prinzip des "Depency Injection" und "Inversion of Control".

26.01.2010 - 22:16 Uhr

Du kannst ja das Compact Framework für deine Mobile-App verwenden und das normale Framework für die Dekstop-App. Dazwischen dann eine Kommunikation mit WindowsCommunicationFoundation beispielsweise.

WCF für das CompactFramework: Messaging in .NET Compact Framework

26.01.2010 - 22:11 Uhr

Du hast in deinem Rechner also zwei Netzwerkarten und möchstest den Rechner dann sozusagen als Router verwenden? Das kannst du einstellen, unter cmd und dann netsh>routing

25.01.2010 - 22:09 Uhr

Mir fehlt der "Schließen"-Button, der zurzeit nur über die Menü-Bar erreichbar ist, irgendwie noch in der Tab-Leiste drinne. Speichern geschieht durchgehend automatisch? Wo kann ich Kategorien anlegen und verwalten?

25.01.2010 - 17:53 Uhr

Die Erhöhung der Datenstream-Position (und anschließendes Auslesen des Streams mit Schleifen) hat beim Abfragen aus der SPS (Port 801) nicht funktioniert:

Habe doch gesagt, dass die Read-Funktion immer ab Position 0 anfängt zu schreiben.

Bezüglich dem zeitlichem Verhalten:
Was meinst du damit? Die Performance der Aufrufe? Wo du schneller deine Daten erhältst? Dann ist die Struktur am schnellsten und bedeutet gleichzeitig den geringsten Aufwand. Da nur ein Handel, nur 2 Kommandos (CreateHandle, Read(Handle)) und nicht für jede einzelne Variable 2. Außerdem erhältst du dann ein Telegramm mit vielen Daten, nicht viele Telegramme in denen jeweils 1 Bit Informationen und 40 Byte Header steht!

25.01.2010 - 15:37 Uhr

Wenn die Variablen direkt aus der I/O kommen und ihr die PLC garnicht benötigt, kannst du diese auch direkt aus der I/O-Task auslesen (Port 300).