Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Portal
  • |
  • Mitglieder
Beiträge von gfoidl
Thema: Async Await Verständnis Probleme
Am im Forum: Grundlagen von C#

Hallo Magier69,

bei deinen Tests hat es keinen Vorteil.

Stell dir aber vor du willst eine IO-Operation (Input, Output) wie z.B. Netwerkzugriffe ala Datenbankabfrage, Web-Request, etc. durchführen so würde bei


var result = service.GetData(...);
UseResult(result);
der ausführende Thread blockiert werden, bis das Ergebnis vorliegt. Das ist nicht ideal.

Daher gibt es asynchrone IO-Vorgänge, bei denen ein Task erzeugt wird und keinen Thread blockiert, sondern bei "Abschluss" des IO-Vorgangs ein sogenannter IO-Thread vom ThreadPool verwendet wird um das "Callback" durchzuführen. Hier eignet sich async/await, da eleganter Code geschrieben werden kann der leserlich ist.


var result = await service.GetDataAsync(...);
UseResult(result);
service.GetDataAsync gibt dabei eine Task zurück, der C#-Compiler erkennt das async/await und erstellt für dich Code der sehr grob analog zu


Task resultTask = service.GetDataAsync(...);
resultTask.ContinueWith(t => UseResult(t.Result));
ist. Da ist der "await Code" schon leserlicher, v.a. wenn mehrere awaits in einer Methode sind.

mfG Gü

Thema: .NET Core und .NET 5 Updates kommen mit dem Windows Update
Am im Forum: Szenenews

Hallo,

ich würde lieber auf die Original-Ankündigung verweisen anstatt zu einem Artikel der im Grunde nur die Info zusammenfasst und selbst auch auf diesen Blog-Beitrag von MS verweist.

mfG Gü

Thema: Die Planung für .NET 6
Am im Forum: Szenenews

Hallo,

Randbemerkung: https://themesof.net/ ist eine Blazor-Anwendung.

mfG Gü

Thema: Coding Styles Horror
Am im Forum: Smalltalk

Hallo,

ein Bug sollte sich im Idealfall durch (Unit-) Tests reproduzieren lassen und falls nicht, so sollte dafür ein Test erstellt werden. Auch damit es später einmal zu keiner Regression kommen kann.

Gibt es jedoch bereits Tests mit passenden Test-Argumenten und der Bug lässt sich dennoch nicht reproduzieren, so mag es u.U. auch am Test-Code selbst liegen.


actual.Should().BeSameAs(actual);

Notiz aus dieser Geschichte:
In solch einem Fall durch bewusste Fehl-Eingaben für den Test, so dass dieser zwangsweise fehlschlagen muss, eine Validierung vom Test-Code vornehmen.
Schlägt der Test nämlich nicht fehl, so ist der Test-Code faul.

Weitere Infos dazu:
Testgetriebene Entwicklung
What is red/green testing?

mfG Gü

Thema: Wie mache ich aus zwei Arrays ein multidimensionales Array?
Am im Forum: Grundlagen von C#

Hallo aloqqq,

Zitat
multidimensionales Array
Muss es ein multidimensionales Array sein?
"Jagged arrays" werden von der .NET Runtime besser unterstützt, falls Leistung ein Kriterium ist.

Auch bieten die jagged Arrays die Möglichkeit die Matrix als Tupel von Spaltenvektoren zu speichern -- du hast das Layout in der Hand. Für dein Beispiel wäre es dann einfach den Vektor in die jeweilige Spalte zu kopieren.


int[] col0 = { 1, 2, 3, 4 };
int[] col1 = { 5, 6, 7, 8 };

int[][] matrix = new int[2][];
matrix[0]      = new int[col0.Length];
matrix[1]      = new int[col1.Length];

col0.CopyTo(matrix[0], 0);
col0.CopyTo(matrix[1], 0);

Es ist auch möglich die Matrix nur in einem (1d) Array zu speichern, so dass einfach Spaltenvektor and Spaltenvektor gehängt wird. Der Zugriff erfolgt dann via entsprechenden Indexer. Grob z.B. so


using System;

int[] col0 = { 1, 2, 3, 4 };
int[] col1 = { 5, 6, 7, 8 };

Matrix matrix = new(4, 2);
matrix.SetColumnVector(col0, 0);
matrix.SetColumnVector(col1, 1);
matrix.Print();

public class Matrix
{
    private readonly int[] _storage;
    private readonly int   _rows;
    private readonly int   _cols;

    public Matrix(int rows, int cols)
    {
        // Argumente sollten hier validiert werden, auch ist auf potentiellen Overflow
        // (durch die Multiplikation) zu achten!
        int size = rows * cols;
        _storage = new int[size];
        _rows    = rows;
        _cols    = cols;
    }

    // Wir verwenden ein "ref return", es wird also die Referenz zum Matrix-Element
    // zurückgegeben. Das erspart uns die Implementierung eines "setters".
    public ref int this[int i, int j]
    {
        get
        {
            if (i ≥ _rows) throw new ArgumentOutOfRangeException(nameof(i));
            if (j ≥ _cols) throw new ArgumentOutOfRangeException(nameof(j));

            // Matrix wird spaltenweise (als Tupel von Spaltenvektoren)
            // gespeichert
            int index = j * _rows + i;
            return ref _storage[index];
        }
    }

    public void SetColumnVector(int[] vector, int j)
    {
        if (vector.Length != _rows) throw new ArgumentException(/* ... */);

        int index = j * _rows;
        Array.Copy(vector, 0, _storage, index, vector.Length);
    }

    public void Print()
    {
        for (int i = 0; i < _rows; ++i)
        {
            for (int j = 0; j < _cols; ++j)
            {
                Console.Write($"{this[i, j]}\t");
            }
            Console.WriteLine();
        }
    }
}


mfG Gü

Thema: Wie kann ich das Fenster "Solution Explorer" in Visual Studio 2019 öffnen?
Am im Forum: Entwicklungs- und Laufzeitumgebung (Infrastruktur)

Hallo MMazi,

ja, ist das gleiche -- nur halt in deutscher Sprache.

Aber probiers doch einfach aus (mit dem Draufklicken) ;-)

mfG Gü

Thema: [gelöst] Infos über .NET 5: Änderungen bei der Interoperabilität (Bericht auf heise.de)
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

Hallo nochmal,

das muss ich noch ergänzen.

Aaron Robinson, der Autor dieses Features in .NET, hat https://github.com/AaronRobinsonMSFT/DNNE erstellt und baut auf dem Vorgenannten auf. Hier ist es möglich per UnmanagedCallersOnlyAttribute den nativen Export zu erzeugen, aber nicht in .NET 5 selbst.

mfG Gü

Thema: [gelöst] Infos über .NET 5: Änderungen bei der Interoperabilität (Bericht auf heise.de)
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

Hallo dannoe,

danke für den Link zum Artikel. Aber dieser ist wirklich schlecht recherchiert und suggiert dass es genügt UnmanagedCallersOnlyAttribute auf eine statische Methode zu setzen und gut ist es. Das ist bei Weitem nicht so (und der Autor sollte sich besser mit anderen Themen beschäftigen).

UnmanagedCallersOnlyAttribute teilt dem JIT mit, dass die so markierte Methode ausschließlich von nicht-verwaltetem Code (~ nativen Code) aufgerufen wird. Somit wird als "function pointer" (erwähnt auch in voriger Antwort) eine leichtgewichtigere Version erstellt, als wenn die Methode auch von managed Code aufgerufen werden würde.

Der wesentliche Hinweis zu Write a custom .NET Core host to control the .NET runtime from your native code fehlt im Artikel, denn somit sind die "native exports" möglich (aber auch schon vor .NET 5, ich glaube fast ab .NET Fx 1.0, also seit Beginn an nur wurde es "vereinfacht" und performanter gemacht).

mfG Gü

Thema: [gelöst] Infos über .NET 5: Änderungen bei der Interoperabilität (Bericht auf heise.de)
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

Hallo pollito,

Zitat
falschen Suchbegriffe
mit ".net 5 native exports" wirst du fündig.

Ganz trivial ist die Sache aber nicht, da die CLR selbst gehostet werden muss, anders kann JIT-kompilierter IL-Code auch nicht ausgeführt werden.
Die Pakete, die du finden wirst, machen das nicht anders, nur teilweise eben für dich.

Ich finde die zitierte Aussage vom Artikel ein wenig irreführend bzw. verspricht sie mehr als es ist.

Der "klassische Weg" mit nativen Anwendungen zu kommunizieren bleibt dass .NET eine native Bibliothek aufruft und der native Teil per Callback wieder in .NET zurückrufen kann.
Der Callback war bisher ein Delegate, das wird sich aber mit "function pointers" (von C# 9) ändern.

mfG Gü

Thema: Wie kann ich das Fenster "Solution Explorer" in Visual Studio 2019 öffnen?
Am im Forum: Entwicklungs- und Laufzeitumgebung (Infrastruktur)

Hallo,

es gibt in VS auch eine nette / praktische "search bar".
Ctrl + Q --> Eingabe (hier "solution explorer") --> die Eregbnisse passen meist

mfG Gü

Thema: Coding Styles Horror
Am im Forum: Smalltalk

Hallo,


private static string GetXyzInstanceString()	// Xyz changed from actual name
{
	// We are going to hardcode the value here to 3 (a random number) so that we don't have to
	// ...
	int id = 3;
	return id.ToString(CultureInfo.InvariantCulture);
}

wurde geändert zu


private static string GetXyzInstanceString()	// Xyz changed from actual name
{
	// We are going to hardcode the value here to 3 (a random number) so that we don't have to
	// ...
	return "3";
}

Immer KISS berücksichtigen.

mfG Gü

Thema: Wie gebe ich den Speicher bei Arrays oder Listen wieder frei?
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

Hallo BerndFfm,

die Ursache / Lösung der anderen ist die sauberste Art und Weise das zu handhaben.
Tipp: VS Performance Profiler -> .NET Object Allocation Tracking, dort kannst du die "Wurzeln" betrachten.

Sonst ev. auch Weak References.

mfG Gü

Thema: Unicode-Emojis tun nicht :)
Am im Forum: Wünsche und Kritik

Hallo,

Zitat von mycsharp.de ist nun auf Azure umgezogen
Wir haben damit eine Basis, die es uns insgesamt vereinfacht langfristig von phpBB ganz weg zu kommen, woran wir parallel bereits arbeiten.
Zitat
Ob auch ein neues Frontend geplant ist, weiß ich nicht.
Technisch gesehen wird das Frontend neu, basiert wie das Backend auf ASP.NET Core 5 und Razor.
Das Erscheinungsbild bleibt aber (zumindest vorläufig) sehr nahe am bisherigen.

Nähere Infos aber dann wenn es soweit ist.
Und gleich vorweg: es ist dann soweit, wenn wir glauben dass es soweit ist ;-)


mfG Gü

Thema: Welches Datenbanksystem für VS und meinen Anforderungen?
Am im Forum: Datentechnologien

Hallo Sebrahi,

da kannst du jede Datenbank verwenden (außer Access, denn das ist keine Datenbank).
Nimm SQL Server Express. Da ist auch das "Tooling" für VS super.

mfG Gü

Thema: .NET 5: Aktueller Stand zu Intrinsics bzw. SIMD-Unterstützung?
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

Hallo MrSparkle,

Zitat
auf eigenen Vektor-Implementierungen

Angenommen diese eigenen Vektoren wären structs. Dann ist es auch möglich diese in einen HW-Vector zu lesen. Z.B. (ab .NET Core 3.1):


using System.Runtime.CompilerServices;
using System.Runtime.Intrinsics;

public static class MyVectorExtensions
{
    public static Vector256<double> ToVector256(this My3dVector vector)
    {
        return Unsafe.As<My3dVector, Vector256<double>>(ref vector);
    }
}


public struct My3dVector
{
    public double X;
    public double Y;
    public double Z;
}
(Gleiches ginge auch für Vector3)

Unsafe.As<TFrom, TTo> entspricht einem reinterpret_cast in C++.
Achtung! Hier ist nicht nur die Klasse Unsafe, sondern auch die Verwendung.
  • wird Unsafe verwendet, so kann der JIT keine Typprüfungen durchführen
  • im Beispiel hier kann der Vector256<double> 4 Elemente aufnehmen, die Struct definiert aber nur 3, daher ist das 4. Vector256<double>-Element Müll
  • wegen letztem Punkt wird über die Grenzen der Struct hinausgelesen und das kann zu einer AccessViolation führen -- es ist zwar sehr unwahrscheinlich dass das tatsächlich passieren mag, aber es soll dennoch darauf hingewiesen werden

Würde ein Vector128<double> verwendet werden, so hätten nur 2 doubles-Platz und somit kann die gesamte Struct nicht gelesen werden.

Diese Art des Speichern von 3d-Vektoren wird Array of Structures genannt und ist eher ungünstig, da entweder zuviel od. zuwenig gelesen wird.
Auch sind etliche Operationen nur unhandlich durchzuführen.

Daher gibt es auch die Möglichkeit der Structure of Arrays, welche diese Nachteile nicht haben und meist günstigere Implementierungen nach sich ziehen.
Allerdings bedeutet das oft auch, dass wesentliche Teile vom Code angepasst werden müssten.
Zitat
Wenn man das als SSE umschreibt
Mit dem verlinkten Artikel musst du aufpassen, denn da wird float verwendet (zu erkennen an der s postfix der Befehlen (s...single, d...double)).
Für double müsste dann AVX (256bit) verwendet werden und da kann es mit dem mischen (shuffle) problematisch werden, denn AVX ist "eigentlich" nur 2xSSE und d.h. ein Shuffle über die "Lanes" geht nur mittels "Permute" ;-) (ich will damit ausdrücken: es wird komplizierter).

Das Kreuzprodukt ist aber (ähnlich wie Matrizenmultiplikation) ohnehin ein schwieriges Beispiel. Aber bei deinen Anwendungen wohl eine sehr häufig verwendet Operation.


mfG Gü

Thema: .NET 5: Aktueller Stand zu Intrinsics bzw. SIMD-Unterstützung?
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

Hallo MrSparkle,

Zitat
JitIntrinsicAttribute
RyuJIT ist der aktuelle JIT-Compiler von .NET und wie so gut wie jeder Compiler arbeitet auch dieser in "Phasen". Ein der erste Phasen ist das "Importieren".

Mit dem JitIntrinsicAttribute (bzw. nach dem Umbenenne nur mehr IntrinsicsAttribute) wird dem RyuJIT mitgeteilt, dass der Typ od. die Methode welches so attributiert ist, speziell zu behandeln ist. D.h. es wird nicht der dort angegebene (IL-) Code verwendet, sondern der JIT importiert spezialisierten Code.

Das ist ein Workaround und nicht mehr, mit dem bestimmte Einschränkungen seitens C# / IL umgangen werden.

Ein Beispiel dazu ist die Implementierung von Span<T>.
Aktuell ist es nicht möglich in einer ref struct ein Feld zu haben das ebenfalls eine ref ist (sollte aber mit C# 10 kommen).
Daher wurde mittels eines ByReference diese Beschränkung umgangen und um möglichst effizienten Maschinencode erzeugen zu können benötigt der RyuJIT eine Sonderbehandlung und genau diese wird mit Intrinsic angegeben.

Da Intrinsic ein Implementierungsdetail ist, wurde es auch als internal deklariert.

Das Bestreben vom .NET-Team ist sowohl C# als auch ggf. IL / allgemeiner: die Plattform so weiter zu entwickeln dass dieser Workaround nicht nötig ist. (Da mit C# geschriebener Code wesentlich portabler ist als Spezialisierungen in C++).

Anm.: CoreRT war / ist hierzu ein "Versuchsfeld" das Vieles direkt in C# implementierte und auf native Implementierungen -- sofern möglich -- verzichtet. Teile davon werden nach und nach zu .NET (Core) portiert.
Zitat
IntrinsicAttribute geben sollte, mit dem man Methoden für eine spezielle Optimierung durch den JIT-Kompiler markieren kann
Ich denke das wurde so um 2015 verlautbart und war wohl eher ein Wunsch als Wirklichkeit.
Angelehnt war das vermutlich an die "auto vectorziation" Möglichkeiten moderner nativer Compiler (wie gängige C/C++ Compiler), die aber auch nicht jeden Code behandeln können, sondern eher nur einfachen schleifenbasierten Code durch Abrollen (Unrolling) und Anwendung von SIMD-Registern.

Einem JIT steht wegen dem "just in time" diese Möglichkeit nicht zur Verfügung, da die auto-vectorization zeitintensiv ist und somit in der knappen dem JIT zur Verfügung stehenden Zeit nicht durchführbar ist.

Nun hat der aktuelle RyuJIT ab .NET Core 2.1 die Möglichkeit der "Tiered Compilation", d.h. es wird mehrstufig kompiliert. In Tier-0 gibt es kaum Optimierungen, so dass der Programmstart zügig voranschreiten kann. Wird eine Methode mehrmals aufgerufen, so dass sie "heiß" wird und wenn diese Aufrufe nach der Startphase ist, so wird der Code dieser Methode mit mehr Optimierungen in Tier-1 kompiliert.
Hier gibt es aktuell verschiedene Diskussionen über weitere Möglichkeiten um noch "optimaleren" Code zu generieren. Dazu zählen Profilinformationen die in Tier-0 gesammelt werden, eine weitere Optimierungsstufe mit Tier-2 usw. Konkret ist hier noch nichts.

Für einen hypothetischen Tier-2 könnte auto-vectorization angewandt werden.
Aber wie vorhin erwähnt klappt das eigentlich nur für simple Schleifen recht gut. Sobald Tensoren höherer Stufe behandelt werden, fehlt dem Compiler einfach das Wissen über die genaue Intention was der Programmierer will und wie die Speicherzugriffe, etc. genau zu erfolgen. Um das zu lösen gibt es mMn zwei Möglichkeiten:
  • eine angepasstere Programmiersprache für Tensor-Rechnung (und / oder Fortran verwenden ;-))

  • den maschinennahen Teil mit HW-Intrinsics (HW...hardware) selbst programmieren

Auch wenn aktuelle C/C++ Compiler auto-vectorization, etc. können, werden "kritische Bereiche" nach wie vor mit Intrinsic (händisch) programmiert, da dies schon ein großer Schritt nach vorne vom Programmieren in Assembler ist.
C# / .NET wird hier keine Sonderrolle einnehmen können, noch dazu mit "time constraints", welchen der JIT -- unabhängig vom Tiering -- unterliegt.

Das Versehen einer Methode od. eine Types mit einem Attribut ist bei Weitem nicht ausreichend um spezielle Optimierungen zu ermöglichen bzw. würde das Ergebnis wohl nie so gut werden, als wenn der Programmierer, der die Aufgabe (hoffentlich) genau versteht, selbt optimierten Code schreibt. Dazu wird das Thema einfach schnell sehr komplex, da auch die super-skalaren CPUs mit ihren Pipelines, CPU-Caches, jede Menge Latenzen usw. einspielen. Ohne Profiler auf Maschinencode-Ebene und Betrachtem vom erzeugten Maschinencode geht es hier nicht mehr und das kann mühselig werden (außer man empfindet daran Gefallen ;-)).

Ich würde diese Vorstellung als Zukunftsmusik abtun, die in den nächsten Jahren in .NET wohl nicht spielen wird und in nativen Sprachen wohl auch nur leisen Töne von sich geben wird.

Analog dazu gibt es aktuell auch kaum ein Projekt das wirklich GPU-Code aus herkömmlichen Code automatisch erzeugen kann, der "sauber" läuft und an händisch geschriebenen (z.B. CUDA) GPU-Code herankommt.

Der von dir verlinkte Blog-Beitrag über die HW-Intrinsics ist zwar ein Jahr alt, aber vom Inhalt her aktuell.
Die HW-Intrinsics sind Teil der .NET-API-Landschaft und da ändert sich dann nichts mehr (genauso wie ArrayList seit .NET 1.0 immer noch dabei ist).
Ein paar Verwendungsmuster haben sich herauskristallisiert, aber im Wesentlichen passt der Inhalt dieses Blogs.
Zitat
alle wichtigen Methoden in allen relevanten Befehlssätzen neu zu implementieren müssen, scheint mir unverhältnismäßig mehr Aufwand zu sein.
Es gibt 2 Arten von vektor-gestütztem Code in .NET
  • Vector2, Vector3, Vector3 und Vector<T> aus System.Numerics
  • Vector128, etc. aus System.Runtime.Intrinsics

Grob gesprochen sind letztere nur Typen, welche dann mittels den Methoden aus Sse2, Avx2, AdvSimd usw. bearbeitet werden.
D.h. auch dass es je nach Zielplattform und CPU-Unterstützung getestet werden muss um so unterschiedliche Code-Pfade haben zu können. Einen Software-Fallback, falls es keine Unterstützung gibt, sollte auch vorhanden sein.
(Außer du weißt dass der Code eh nur auf einer bekannten Plattform z.B. auf einer Intel i7 CPU läuft, dann kannst du diese Test sparen).

Die Typen aus System.Numerics bieten Methoden zum Bearbeiten an und übernehmen die "Unterstützungs"-Test für dich und haben auch einen Software-Fallback implementiert.
Allerdings ist -- zumindest aktuell* -- der erzeugte Maschinencode mit den HW-Intrinsics meist besser. Zudem können mit den HW-Intrinsics, hier am Beispiel von x64 erklärt, bei Vektoren zuerst "AVX-Schritten" (256 bit), dann der Rest in "SSE-Schritten" (128 bit) und der Rest skalar verarbeitet werden, währen die SN-Vektoren nur eine der Vektor-Größen (entweder AVX falls unterstützt von der CPU, sonst SSE) kennen.

Ein Vorteil der HW-Intrinsics ist auch, dass es viele Referenz-Implementierungen für Problem in C++ mit intrinsics gibt und diese sind somit einfacher zu C# zu portieren.

Klar erhöht sich der Aufwand so (fast immens), aber die Ziel-Gruppe der HW-Intrinsics ist auch nicht das breite Publikum sondern eher die Nische, welche "bestmögliche Geschwindigkeit" haben will (und dazu zählen die .NET Innerein selbst).

* es ist geplant die Implementierungen von System.Numerics-Vektoren neu zu implementieren auf Basis der HW-Intrinsics, die erst später Einzug in .NET hielten als die SN-Vektoren die schon länger da sind
Zitat
Da ich viel mit 3D-Grafik zu tun habe, wäre die Kompilierung in CPU-spezifische Befehlssätze sehr sinnvoll.
Schau dir dazu einmal Vector3 und Vector4 genauer an.
Die wurden für solche Szenarien eingeführt und haben viele Anleihen von DirectX-Math (od. wie das genau heißt) genommen.
Diese Vektoren können auch als Felder in eigenen Typen verwendet werden (die HW-Intrinsics Vektoren übrigens auch).
Auf ein Umschreiben / Anpassen deines Codes wirst du da nicht herumkommen (wie erwähnt schaffen das nicht einmal native Compiler die genügend Zeit dafür haben).
Zitat
um eigenen Code JIT-optimieren zu können?
Im Release-Build führt der JIT seit jeher Optimierungen durch.
(Ich weiß aus dem Kontext, dass du nicht danach gefragt hast).

mfG Gü

Thema: Wird ein Objekt, das an einen Task übergeben wird, bei Veränderungen vom Main Thread mit verändert?
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

Hallo ck82,

ich stimme Abt da ganz zu.

Zitat von Abt
Daher wird auch nicht "einfach so" eine Kopie erstellt.
Das ist eben die Krux dabei, dass beide Threads (der Main-Thread, sowie jener der die Aktion von Task.Run mit einem ThreadPool-Thread ausführt) auf dasselbe Objekt arbeiten und du nicht bestimmen kann wer wann welche Ändeurng zuerst durchführt. Es ist somit durchaus möglich, dass in den Daten deines Objekts Müll entsteht. Das ist die von Abt erwähnte "Race Condition".

Abhilfen gibt es dafür ein paar:
  • Thread-Synchronisierungen (suche mal danach, da gibt es Lektüre fürs WE -- Vorzugsweise: Basic Synchronization aus Threading in C# / Joseph Albahari)

  • immutable Typen verwenden, d.h. Typen die nach der Instanzierung nicht mehr geändert werden können und somit gibt es kein Race
    (Anm.: das ist mit ein Grund warum mit C#9 Records eingeführt werden, neben dem weniger Tipparbeit für Datenklassen)

  • asynchron arbeiten, aber ohne gleichzeitige Zugriffe auf das Objekt, z.B. mittels einer Pipeline in der das Objekt von "Station zu Station" gereicht wird

Aber berücksichtige
Zitat
erzählst, was Dein Vorhaben ist

mfG Gü

Thema: Warum bleibt beim Ausführen des Report Builders eine Spalte leer?
Am im Forum: Datentechnologien

Hallo Alpi1,

kannst du auch die Berichtsdefinition zeigen bzw. dort prüfen wie und ob die Stueli-Spalte verknüpft ist?

So ist es nur raten und das ist eher wenig zielführend.

mfG Gü

Thema: Was ist die effektivste Möglichkeit, eine Memory-Datenbank mit Tabellen zum Testen zu erstellen?
Am im Forum: Datentechnologien

Hallo ThomasE.,

für SQL Server:
Kannst du SQL Server Express im Docker-Container verwenden?
Dann hast du eine richtige DB, Testdaten kannst du einfügen und so ein Image erstellen das zum Testen verwendet werden kann (ev. auch via CI).

Für andere DBMS halt ein anderes Docker-Image verwenden.

EF InMemory ist für einfach Unit-Tests geeignet -- wie schon erwähnt wurde.
SQLite scheitert wenn Schemas verwendet werden, da diese nicht unterstützt werden.

Wenn bei Tests Inserts/Updates durchgeführt werden, achte darauf dass diese in einer Transaktion durchgeführt werden, die dann nach dem Tests zurückgesetzt wird (rollback), damit zwischen den einzelnen Test-Fällen keine Abhängigkeit entsteht.

mfG Gü

Thema: Was ist der Unterschied zwischen volatile und atomar?
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

Hallo Palladin007,

dazu hab ich (leider) keine Muße / Zeit ;-)
Irgendwie interessant wäre es aber ein Buch der Art "Perlen von myCSharp.de" (o.ä.) zu erstellen, denn hier im Forum gibt es schon sehr viele gute tiefgründige Beiträge, die z.T. auch zeitlos sind.

Zitat
Dann wäre ich nur noch mit Fragen stellen beschäftigt und würde das Forum im Alleingang füllen :D
Warum auch nicht?

mfG Gü

Thema: Buch zu den .NET-Internas?
Am im Forum: Buchempfehlungen

Hallo Palladin007,

Zitat
die verschiedenen Möglichkeiten, die Arbeit in mehreren Threads untereinander zu synchronisieren
Auch wenns alt ist, ist es immer noch korrekt und ein "Klassiker": http://www.albahari.com/threading/
An den grundlegenden Dingen wird sich hier auch in Zukunft nichts ändern, da die Konzepte für CPUs und Speichermodelle sich "hier nicht weiterentwickeln". Das wäre ggf. mächtige Brüche mit der Kompatibilität.

http://joeduffyblog.com/ (v.a. die alten Beiträge) sind hier ebenfalls eine gute Quelle, die teils sehr in die Tiefe gehen -- nicht zuletzt wegen Joe Duffys damaligen Job für das entsprechende .NET Team.

mfG Gü

Thema: Was ist der Unterschied zwischen volatile und atomar?
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

Hallo Th69,

Zitat
Und mit Sichtbarkeit auch nicht
Entsprechend dem Speichermodell (memory model) der CPU / Threads geht es bei volatile genau um die Sichtbarkeit (der Werte).
Z.B. dass der Wert nicht in einem Register gehalten werden darf, und somit "unsichtbar" für andere Threads ist, sondern "sichtbar" im Speicher sein muss. Mit "Speicher" sind hier auch allfällige Cache-Hierarchien gemeint und da geht es erst recht um die Sichtbarkeit (der Änderungen).
Zusätzlich wird beim Lesen ein "acquire fence" und ein "release fence" beim Schreiben gesetzt, so dass andere Lese-/Schreibvorgänge in Bezug auf den "fence" nicht umgeordnet werden dürfen. Auch dabei geht es um die Sichtbarkeit.
(Anm.: die "fences" sind auch Begriffe aus dem Speichermodell).

Vllt. hätte ich in der vorigen Antwort bei Sichtbarkeit den Bezug zum Speichermodell explizit herstellen sollen, denn mit Sichtbarkeit kann auch mehr gemeint sein (wie public, private, etc.) und somit hast du (in dieser Hinsicht) recht ;-)
Zitat
der Compiler bzw. das Runtime-System
Auch die CPU ist dabei betroffen.
Der/die Compiler dürfen beim Optimieren den Code nur so verändern, dass die "fences" von volatile erhalten bleiben.
Die Runtime / Execution Engine / VM müssen auch die "fences" erhalten lassen.
Die CPU muss dafür sorgen, dass in Bezug auf die "fences" die Sichtbarkeit des Speicherbereichs gegeben ist und darf keine Pipeline-Optimierungen vornehmen welche eine "fence" verletzen würden.

Intel x84/x64 ist hier von Haus aus eher streng ("strong memory model"), aber z.B. Arm-Prozessoren sind hier sehr locker ("weak memory model"). Daher ist für plattformübergreifenden Code und Threading die Kenntnis der Speichermodelle -- zu einem bestimmten Grade -- nicht ganz unwesentlich.

Einschub:
Kestrel (ein Server von ASP.NET Core) lief anfänglich nur auf x86*. Da in der Cloud immer mehr Arm64-CPUs Einzug halten, gab es folglich den Wunsch dass Kestrel auch Arm64 unterstützt. Wie sich jeder vorstellen kann sind Webserver sehr nebenläufig und parallelisiert. Ein großer Punkt für die Unterstützung von Arm64 war das "weak memory Model" und die korrekte Handhabung der Speicherzugriffen.
Neben ausführlichen Reviews für die Pull Requests werden zur Überprüfung auch jede Menge "Fuzz Tests" durchgeführt, denn gerade bei "Threading" ist nur durch "Hinschauen" nciht so einfach potentielle Fallstricke erkennen zu können.

* wird nur x86 angegeben, so sind Intel kompatible 32-/64-bit Systeme gemeint.
Andernfalls wird explizit von x86 und x64 od. Arm64 / Arm32, etc. gesprochen.
Zitat
volatile kann eben nur auf "atomare" Datentypen angewendet
Danke dass du das ergänzt, ist aber auch nicht ganz korrekt / präzise (obwohl ich deine Intention dahinter sehr wohl verstehe).

volatile für Datentypen die größer als die Wortbreite der CPU sind machen keinen Sinn, da so das Prinzip von volatile nicht umgesetzt werden kann.

Dass der C#-Compiler hier long, double ausnimmt, liegt darin begründet dass .NET Anwendung plattformunabhängig laufen sollen, d.h. sowohl auf x86 und x64 und auf 32-bit Systemen (x86) sind diese beiden Datentypen nicht atomar.

Daher auch das "fast" oben, denn auf x64 sind double und long atomare Datentypen, dennoch kann volatile nicht darauf angewandt werden.
Gleiches gilt für atomare Werttypen auf die volatile nicht angewandt werden kann. Z.B.


public struct Foo
{
    public int A;
}
ist perfekt atomar, dennoch geht volatile nicht.

Als ich meine Antwort verfasste sah ich "atomar" nur in Bezug auf das von mir Zitierte.
Da sehe ich diesen Punkt immer noch als passend an, aber allgemein gesehen ist dieser Punkt zu unpräzise.

Ich bin immer wieder froh, dass es ein Forum gibt welches solche unpräzisen Punkte aufgreift :-)


Hallo Palladin007,
Zitat
Das sind so Details, die ich mir von so einer Lektüre erhofft hätte
Wenn du einen Punkt hast der dich interessiert, so kannst du ja eine Frage im Forum stellen. Irgendwer wird schon eine Antwort schreiben... ;-)

mfG Gü

Thema: Was ist der Unterschied zwischen volatile und atomar?
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

Hallo,

auch wenns in diesem (Unter-) Forum offtopic ist, sollte das nicht unkommentiert stehen bleiben, da es nicht richtig ist.

Sollte das weiterer Diskussion bedürfen, so können wir das auch abteilen.

Zitat
Variablen-Zugriffe scheinbar nicht ganz so atomar sind, wie erst gedacht - aus dem Grund gibt's ja volatile.
Zitat
Die grundlegenden Datentypen wie int, double, float sind in den meisten Programmiersprachen nicht atomar bzw. muss man dafür über andere Typen wie AtomicInteger oder durch volatile dafür sorgen.
volatile hat mit "atomar" nichts zu tun. Das sind zwei verschiedene Dinge -- beide haben ihren Ursprung zwar im "Threading", aber sind dennoch grundverschieden.

volatile ist ein Modifizierer für die Sichtbarkeit der Variable.

"atomar" heißt hier dass der Wert unteilbar (~ Atom) geschrieben / gelesen wird, ohne dass "torn writes / reads" zugelassen werden.
Typen deren Größe der Wortgröße der CPU entspricht werden immer atomar geschrieben / gelesen. sizeof(T) == Wortgröße <=> atomar.
D.h. bei x86 ist int, float atomar. Bei x64 ist double auch atomar.
Referenzen sind -- per Konstruktion -- ebenfalls immer atomar.
Größere Werttypen als Wortgröße der CPU brauchen besondere Behandlung, damit sie atomar verwendet werden können (z.B. durch Interlocked).

So nebenbei: das ist auch der Grund warum Span<T> nur "stack-only" ist, da es ohne Laufzeiteinbußen sonst nicht möglich ist atomare Vorgänge damit abzubilden. Da es eben nur auf dem Stack gestattet ist, gibt es kein Problem mit nebenläufigen Zugriffen.


mfG Gü

Thema: Ist es möglich in ASP.NET MVC (nicht Core) die Startup Klasse hinzuzufügen?
Am im Forum: Web-Technologien

Hallo Peter Bucher,

im Link oben ist auch ein Abschnitt für Global.asax. Geht's damit nicht?

mfG Gü

Thema: Wie entwickle ich am Besten ein Tool, das die Verbindung zum Application-Server prüft?
Am im Forum: Datentechnologien

Hallo eMsentry,

führe einfach eine Dummy-Abfrage zum Application-Server durch.
Wenn du den Server auch beeinflussen kannst, so z.B. eine "Hallo"-Abfrage, die vom Server die Zeit zurückgibt, etc.
So kannst du prüfen ob die Verbindung passt und auch ob die Authentifizierung / Autorisierung soweit OK ist.

Zitat
wegen blockierter Ports oder sonstiges nicht möglich war
Für so einen Zweck macht das sinn. Generell sind solche Tests aber mit Vorsicht zu genießen, da zwischen Test, der OK liefert, und späterer Verwendung viel passieren kann. D.h. im Betrieb kann einfach der Reqeust zum Server abgefeuert werden und falls es ein Problem gibt via Exception-Handling darauf reagieren, z.B. indem ein neuer Versuch nach kurzer Wartezeit durchgeführt wird (siehe dazu Polly).

Auch interessant in diesem Zusammenhang: Health checks in ASP.NET Core

mfG Gü

Thema: Wie kann ich eine for-Schleife zeitversetzt durchlaufen?
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

Hallo Michael1995,

eleganter wie mit dem Timer geht es mit Tasks:


private static async Task FillNotionsAsync(IList<Notion> notions)
{
    for (int i = 0; i < notions.Count; ++i)
    {
        await Task.Delay(100).ConfigureAwait(false);
        notions[i] = new Notion();
    }
}

od. falls du C# 8 verwenden kannst


private static async IAsyncEnumerable<Notion> CreateNotionsAsync(int count)
{
    for (int i = 0; i < count; ++i)
    {
        await Task.Delay(100).ConfigureAwait(false);
        yield return new Notion();
    }
}

mfG Gü

Thema: Politik trifft Git - Umbenennen des Master Branches
Am im Forum: Szenenews

Hallo,

Zitat
primary/secondary
Stellt genauso eine "Ordnungsrelation" dar wie master/slave.

mfG Gü

Thema: Findet dll im Unterordner x64 nicht
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

Hallo Th69,

Zitat
Wie auch immer, am sichersten ist es die DLL aus dem Anwendungsverzeichnis zu laden.


Und der Vollständigkeithalber noch die Erwähnung von NativeLibrary welches mit .NET Core 3.0 Einzug gehalten hat.

mfG Gü

Thema: Findet dll im Unterordner x64 nicht
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

Hallo Th69,

Zitat von Th69
Da diese DLL wohl per [DllImport] eingebunden wird, kann man nur per WinAPI-Funktion SetDllDirectory den Suchpfad ändern, s.a. How can I specify a [DllImport] path at runtime? (Wichtig ist, daß dies vor dem Aufruf der ersten Funktion aus dieser DLL passieren muß).
SO liefert nicht immer die besten Lösungen, v.a. wenn wir hier im Forum etwas (in der FAQ) dazu haben ;-) => 32bit/64bit unmanaged DLL "importen" - wie?


mfG Gü

Thema: [SOLVED] - dotnet publish - unterschiedliche Ergebnisse unter Linux ./. Windows
Am im Forum: Entwicklungs- und Laufzeitumgebung (Infrastruktur)

Hallo LaTino,

gibt es diese Unterschiede auch wenn nur


dotnet publish ./PROJECTNAME/PROJECTNAME.csproj -c Release
verwendet wird?

Die Runtime hat natürlich Unterschiede zwischen den verschiedenen Betriebssystemen. Nur als Beispiel wird für Windows das Windows-API verwendet, während *nix auf die entsprechenden POSIX-APIs zugreift.

Durch die Angabe der Ziel-Runtime --runtime win-x64 wird entweder "cross compiled" od. nicht. Daher kann es -- auch beeinflusst von den NuGet-Referenzen -- zu Unterschieden der Build-Ausgabe kommen.

Konkret kann ich mangels Kenntnis des Projekts aber nicht auf die tatsächliche Ursache zurückschließen.
Zitat
dass ein und derselbe Befehl in ein und derselben SDK-Version zu ein und demselben Ergebnis führt
Dem ist auch so -- bis auf den Unterschied dass ab .NET Core 3.0 bei Windows eine PROJECTNAME.exe erzeugt wird, während bei *nix eine PROJECTNAME erzeugt wird.

mfG Gü