Laden...
U
Uwe81
myCSharp.de - Member
51
Themen
282
Beiträge
Letzte Aktivität
vor 6 Jahren
Dabei seit
26.07.2008
Alter
43
Herkunft
Ludwigshafen
Website
Erstellt vor 6 Jahren

Hallo,

Ich habe ein Array von Enumerables


IEnumerable<T>[] sources;

Typischerweise iterieren diese Enumerables nicht schnell, sind z.B. Dateien aus einem Document Management System. Der Overhead ist hoch, sodass sich wegen der hohen Latenz Parallelisierung lohnen würde, z.B. weil ich bei drei verschiedenen Repositories Dokumente runterlade.

Das Interface gibt mir für ein Repository alle Dokumente als IEnumerable<T>

Jetzt suche ich ein Enumerable, was sich wiefolgt berechnet.
Für jedes Sourceelement gibt es einen kleinen Buffer.
Die Enumerables werden parallel durchlaufen, d.h. wenn der Buffer für ein Enumerable nicht mehr gefüllt ist, wird das nächste Element bereits abgerufen.
Wenn ich für das "merged Enumerable" das nächste Element abfrage, erhalte ich irgend eines aus den buffern der unterliegenen enumerables, oder halt das nächste was da ist.

Ich bin neun in Tasks, PLINQ und parallel foreach. Daher verliere ich mich bei der Implementierung.

Das beste was ich bisher hinbekommen habe ist eine manuelle Implementierung mit Blocking Collections (noch nicht getestet)
Geht das wirklich nicht eleganter?


        public int MaxCapacity { get; set; }
        public IList<IIterateStrategy> IterateStrategies { get; set; };

        public IEnumerable<DSDownloadEntry> Iterate() {
            var collection = new BlockingCollection<DSDownloadEntry>(MaxCapacity);
            var tasks = new Task[IterateStrategies.Count];
            for(int i = 0; i<IterateStrategies.Count; i++) {
                int index = i;
                var strategy = IterateStrategies[index];
                tasks[i] = Task.Factory.StartNew(() => {
                    foreach (var item in IterateStrategies[index].Iterate()) {
                        collection.Add(new DSDownloadEntry() { Container = item });
                    }
                });
            }
            Task.Factory.ContinueWhenAll(tasks, _ => collection.CompleteAdding());
            return collection.GetConsumingEnumerable();
        }

Ergänzung:

Ich habe jetzt nochmal PLINQ versucht:


    class Producer {
        public string Prefix;
        public int Count;

        public IEnumerable<string> GetResults() {
            Random random = new Random();
            for (int i = 0; i < Count; i++) {
                var text = string.Format("{0}{1:000000}", Prefix, i);
                Console.WriteLine("Producing " + text);
                yield return text;
            }
            Console.WriteLine("############### DONE " + Prefix);
        }
    }
    class Program {
        public static void Main() {
            var producers = new[] {
                new Producer() {Prefix = "A", Count = 100000},
                new Producer() {Prefix = "B", Count = 100000},
                new Producer() {Prefix = "C", Count = 100000},
            };

            var merged = from p in producers.AsParallel()
                         from r in p.GetResults()
                         select r;

            foreach (var r in merged) {
                Console.WriteLine("Consumint " + r);
            }
        }
    }

Das Problem hier ist, das der Producer bereits weiterläuft, auch wenn nur wenig abgerufen wird.
Eine ergänzung "AsParallel().WithMergeOptions" hat nichts verändert.

Mein Wunsch wäre eben, dass pro Producer nur wenige Einträge gebuffert werden.

Erstellt vor 10 Jahren

Wenn ich die Anwendung selbst in der Hand hätte, würde ich die Assembly-Aufteilung auch nicht so machen.

So ist es aber, dass die Anwendung meinen Code per COM-Schnittstelle aufruft, ich dann meinerseits eine Methode aufrufe, die mein Control erzeugt und in einem vorgegebenen Rahmen anzeigt. Dabei müssen die Assemblies aber an unterschiedlichen Stellen liegen, insbesondere das Control in einem bestimmten Unterordner des Programms.

Jetzt habe ich es erstmal so gelöst, dass ich mir per Reflection das Command als ICommand hole.

Sollten noch weitere Abhängigkeiten entstehen, muss ich das nochmals überdenken. Allerdings weiß ich garnicht so genau, wo dann das gemeinsam bekannte Interface-Assembly liegen soll. Im Ordner der View? Im Ordner der Logik (die per COM-Interface angestoßen wird).

Erstellt vor 10 Jahren

Hallo!

Ich programmiere gerade ein WPF UserControl, welches in einer fremden Anwendung eingebunden werden soll.

Aus den Anforderungen der Anwendung hat sich folgende Architektur ergeben:
Ein Assembly, welches die BL und das ViewModel beinhaltet.
Ein Assembly, welches das Control beinhaltet.
(ich weiß, dass man BL und ViewModel lieber trennen würde, da aber beides aus 3 bis 6 kleinen Klassen besteht, tut mir das nicht wirklich weh).

Für die Anwendung ist es vorteilhaft, dass die beiden Assemblies sich nicht referenzieren. Soweit funktioniert das auch alles gut.

Das Problem ist nun folgendes:
Mein Control muss ein interface implementieren, welches (z.B.) so aussieht:


interface IApplicationControl {
  public void OnCanExecute(CanExecuteRoutedEventArgs e) { }
  public void OnExecuted(ExecutedRoutedEventArgs e) { }
}

In den EventArgs steht dann jeweils über die OriginalSource der Name des Buttons.

Jetzt würde ich gerne an dieser Stelle quasi ein Command aus dem ViewModel fragen nach CanExecute bzw. in die Execute aufrufen. Also


class MyViewModel {
  public ICommand OkCommand {get; private set;}
}

class MyControl : IApplicationControl {
  public void OnCanExecute(CanExecuteRoutedEventArgs e) { 
    
    if (e.OriginalSource.Name == "Ok"){
        MyViewModel viewModel = DataContext as MyViewModel; //GEHT NICHT!!
        e.CanExecute = viewModel.OkCommand.CanExecute(null);
    }
  }
}

Aber ich kann den DataContext ja nicht auf das spezifische ViewModel casten, weil ich keine Referenz auf das Assembly habe.

Gibt es nun einen "eleganten" Weg, dass ich mir in XAML dieses Command über DataBinding hole, oder muss ich das im CodeBehind über Reflection machen?

Vielen Dank!

Erstellt vor 10 Jahren

Statische Methoden sind solange praktisch, solange du nicht versuchst threads zu verwenden, dann kann es knifflig werden.

Das ist so falsch. Das Problem tritt bei statischen Variablen auf. Gegen Statische Methoden, welche nur Parameter und lokale Variablen haben, spricht nichts. Im gegenteil halte ich das für eine sehr einfache Möglichkeit, Threadsicherheit zu erreichen.

Ist dann zwar quasi prozedurale Programmierung als OOP, aber wenn es zum Problem passt (mathematische Algorithmen o.Ä.) völlig OK.

Es ist sogar so, dass - wenn ich ein Objekt habe, welches einen Algorithmus durchführt und dabei seinen inneren Zustand temporär verändert - ich sehr gerne statische Hilfsmethoden schreibe die eine Instanz erzeugen, den Algorithmus ausführen, die Instanz wegwerfen und das Ergebniss zurückgeben. Quasi um Threadsicherheit zu garantieren.

Zusammenfassend zum Thema Threads:
Trivial threadsicher sind Methoden, die nur Parameter und Lokale Variablen verwenden.

Gefährlich sind immer äußere Zustände. Bei normalen Objekten kann mann dann verschiedene Instanzen anlegen, bei statischen, nicht readonly Variablen hat man ein Problem.....

Erstellt vor 10 Jahren

Getter und Setter verletzen das OOP-Prinzip genauso wie get und set Methoden. Also erstmal garnicht, bei extensivem gebrauch bekommt das ganze aber einen Geschmack.

Du kannst in einem Getter etwas berechnen, also nur weil es ein Getter gibt muss dahinter noch lange kein Feld stehen. Insofern Kapselt ein Getter. Auch ein Setter muss nicht unmittelbar in ein Feld schreiben, könnte also z.B. einen Setter von einem privaten Objekt aufrufen.

Insofern kapseln sowohl Getter und Setter die Implementierung, sind daher guter OOP-Stil.

Ein Problem wird das ganze dann, wenn man - weil es ja so schön einfach ist - aus jedem privaten Feld ein Property macht ung {get; set;} dahinter schreibt. Dann verletzt man die OOP-Prinzipien.

Generell gilt für alles, was public ist: So viel wie nötig, so wenig wie möglich. Das gilt auch für Properties.

Erstellt vor 10 Jahren

Ich finde immernoch, dass die meisten Argumente eigentlich den Kern des Problems nicht treffen.

Die abstrakte Basisklasse ist ein Implementierungsdetail, was nach außen nicht bekannt ist. Ich kann es jederzeit ändern.

Wenn nun 8 Klassen von dieser Basisklasse ableiten, für eine neunte passt es nicht mehr, dann implementiere ich halt das Interface direkt. Wenn ich eine Klasse erweitern will und die Basisklasse nicht mehr passt, dann implementiere ich das Interface direkt oder erbe gar von einer anderen Basisklasse.

In all diesen Fällen bekommen die Benutzer des Interfaces das garnicht mit, weil die Entkopplung eben über das Interface stattfindet. Die Basisklasse entspricht eher einer "privaten Vererbung" aus dem C++-Umfeld.

Daher würde ich das weiterhin machen und mich um ggf. auftretende Probleme erst später kümmern. Denn Probleme mit einer Klasse in dieser Architektur können nur dann auftreten, wenn sich die Aufgaben dieser Klasse ändern. Dann muss ich sie sowieso anfassen. Und die Entkopplung zu den Verwendungen der Klasse bleibt durch das Interface unverändert.

Erstellt vor 10 Jahren

Ich finde das Konzet eigentlich sehr sauber, verwende es selbst sehr gerne.
Du musst nur sicherstellen, dass die Nutzer sich eben nur auf das generelle Interface verlassen und nicht auf Implementierungsdetails der abstrakten Klasse.

Die Seperation of Concerns:* Interface stellt das nach außen verbindliche Interface dar.

  • Abstrakte Klasse vermeidet Redundanzen in der Implementierung.

Die abstrake Basisklasse bleibt ein Implementierungsdetail, was du jederzeit entfernen könntest ohne dass die Anwendenden Klassen etwas davon mitbekommen.

Ich halte das Konzept sogar eher für eine Best Practice.

Erstellt vor 11 Jahren

Hallo!

Bisher habe ich reichlich Erfahrungen mit GUI-lastigen Desktop-Anwendungen, werden nun aber eine Client/Server-Anwendung entwickeln müssen. Während sich für einige Bereiche mein Bild schon geschärft hat, stocher ich in anderen Ecken noch im Nebel...

Folgendes (fiktives, aber dem Problem nahe kommendes) Szenario.

In einer Universität teilen sich drei Fachbereiche ein Gebäude. Jeder Fachbereich hat im Wesentlichen seine eigenen Räume, aber einige große Hörsäle werden auch gemeinsam genutzt. Es soll nun eine Software entwickelt werden, um die Vorlesungen zu planen. Außerdem sollen Studenten per Internet / Mobile App sich zu anmelde-beschränkten Kursen und / oder Übungen anmelden zu können.

Es gibt folgende Komponenten:*Pro Fachbereich einen lokal installierten Planungs-Client, mit dem die Vorlesungen dieses Fachbereichs geplant werden können. Da dieses durch Optimierungsalgorithmen unterstützt wird und recht komplexe Interaktionen benötigt, ist eine Implementierung als HTML im Browser nicht sinnvoll. *Einen zentralen Server, auf dem der aktuelle Plan gespeichert ist und mit dem die Planungs-Clients kommunizieren. U.A. muss es z.B. möglich sein, dass ein Planungs-Client einen gemeinsam genutzten Hörsaal für einen gewissen Zeitraum sperrt, um in diesem umzuplanen (Pessimistic Locking). Dieses sollte dann allen anderen Clients instantan angezeigt werden (also muss Push vom Server zum Client gehen). *Es kann notwendig sein, dass Client und Server nur über Internet verbunden sind, also die Server-Schnittstelle im Internet steht (Sicherheit ist also wichtig). *Es gibt eine Website bzw. diverse Mobile Apps, mit denen Studenten sich zu Übungen / Vorlesungen anmelden können bzw. den vorläufigen Plan sehen. *Es soll möglich sein, den Studenten Änderungen für angemeldete Kurse per Push-Nachricht zu senden.

Wie gesagt, das Beispiel ist fiktiv, kommt aber unserem Praktischen Problem recht nahe und ich muss jetzt nicht einen Roman zur Erläuterung der realen Anwendung schreiben.

Folgende Design-Entscheidungen habe ich bisher getroffen: *Die Mobile Apps werden mit HTML5 erstellt, um nicht für iOS/Android/Windows entwickeln zu müssen. *Die Kommunikation des Servers zu den Mobile Apps und der Studenten-Website soll über eine REST-Schnittstelle erfolgen. Mir gefällt dafür NancyFX recht gut, zumal ich mit einem ähnlichen Micro-Framework privat schon gute Erfahrungen gemacht habe (Slim unter PHP, obwohl ich ansonsten PHP hasse.....) *Ob die Website eine Single Page Application wird oder ich immer den RoundTrip über den Server gehe und HTML ausliefere, weiß ich noch nicht. Haber aber ein ganz gutes gefühl für die Trade Offs *Der Planungs-Client wird eine WPF-Desktopanwendung. Diese wird immer zusammen mit dem Server entwickelt, es gibt nur wenige lokale Installationen und der Komfort währen der Planung ist wichtiger als das Rollout. *Authentifizierung vermutlich mittels JSON Web Token.

Bei folgendem Punkt bin ich etwas verloren: *Wie mache ich bei der Schnittstelle zu den Apps die Push-Nachricht? Ist SignalR dort eine gute Wahl? Quasi dass man als Message sendet "Es gibt was neues, fordere mal folgende Ressourcen an" und dann einen Link mit sendet.

*Welche Kommunikation zwischen Planungs-Client und Server verwende ich? Die sind eng gekoppelt, müssen niemals an andere Systeme angebunden werden und werden immer zusammen entwickelt. Die Kommunikation kann aber evtl. über Internet stattfinden, sollte also sicher sein.
--> Mir erschien WCF das Mittel der Wahl, habe aber jetzt viele Warnungen gehört, dass es sehr komplex sei.
--> Eine REST-Schnittstelle ist eine sehr lose Kopplung. Ist diese nicht hier zu Aufwändig und zu viel Overhead? Zumal dann die Push-Problematik dann nicht gelöst ist, oder auch SignalR?
--> Remoting wirkt einfacher, soll aber wohl veraltet sein und nur noch aus Kompatibilitätsgründen mitgeliefert werden. Aber für ein neues Projekt
--> TCP/IP Sockets: Ist halt sehr low level, dafür versteht man vermutlich, was man tut. Aber bekommt man als Netzwerk-Anfänger wirklich die Probleme in den Griff
--> Eine Messaging Infrastruktur (MSMQ). Aber brauchen wir wirklich Messaging? Gefühlt ist das eher das klassische RPC?

Insbesondere der letzte Punkt ist derzeit schwierig. Es gibt diverse Möglichkeiten, mir sind die Tradeoffs aber nicht klar. Gibt es dazu Meinungen, Tipps oder evtl. sogar Hinweise zu Tutorials / Büchern, wo die verschiedenen Technologien verglichen werden und Guidelines, wann man welche nimmt?

Vielen Dank für Tipps,
Uwe

Erstellt vor 12 Jahren

Stimmt, im allgemeinen führt das vermutlich zu Problemen.

Da ich die Kombination von IFoo und IBar ja im voraus kenne, habe ich nun einfach ExtensionsMethods geschrieben.


static void RegisterBar<TBar>() where TBar:IBar {
    builder.Register<IBar, Bar>();
    builder.Register<IFoo, Bar>();
}

Irgendwie habe ich erst versucht, das über ein RegistrationModule zu machen, aber da das später immer im Code konfiguriert wird, kann ich es eigentlich auch direkt per EtensionMethod machen (dennoch ist es interessant, RegistrationModules zu kennen).

Vielen Dank für den Fingerzeig in die richtige Richtung,
Uwe

Erstellt vor 12 Jahren

Hallo, der Titel ist etwas blöd, aber in Code ist es leicht zu erklären, was ich suche...


using LightCore;

interface IFoo {
    void DoFoo();
}

interface IBar : IFoo {
    void DoBar();
}

class Bar : IBar {
    public void DoFoo() {}
    public void DoBar() {}
}

class Program {
    public static void Main() {
        var builder = new ContainerBuilder();
        builder.Register<IBar, Bar>();
        var container = builder.Build();
        var foo = container.Resolve<IFoo>();
    }
}

Bei der letzten Zeile fliegt eine Exception. Ist auch klar, weil kein IFoo registriert ist. Allerdings kennt der Container ja ein IBar und weiß, dass das auch ein IFoo ist. Gibt es eine Möglichkeit, dass das automatisch aufgelöst wird?

Was geht (mir aber nicht so gut gefällt) ist


builder.Register<IBar, Bar>();
builder.Register<IFoo, Bar>();

oder


builder.Register<IBar, Bar>();
builder.Register<IFoo>(c => c.Resolve<IBar>());

Mir ist das ganze deshalb wichtig, weil ich ein Framwork entwickel, welches dann von anderen verwendet wird. Innerhalb des Framworks will ich (aus Kapeselungsgründen) möglichst spezialisierte Interfaces durch die Gegend reichen, nach außen will ich aber für den Benutzer meines Frameworks die Konfiguration des DI Containers möglichst einfach halten.

Viele Grüße und vielen Dank,
Uwe

10 von 282 Beiträgen