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 Palladin007
Thema: Projektvorstellung: LocalizeMe (Typsichere Lokalisierung)
Am im Forum: Projekte

Zitat von IntelliSoft
Was ich nicht konnte, obwohl es lt. allen hier leicht funktionieren sollte, war es mehrere unabhängige Sprachen/Formatierungen in einer Ansicht zu haben.
Vl. hat ja jemand die Geduld, mir zu zeigen, wie mein kleines Programm mit den Board mitteln, leicht zu lösen geht.
Du meinst, Du suchst eine Übersicht aller Texte für alle Sprachen?

Das habe ich schon genannt: RESX-Manager
ResXManager - Visual Studio Marketplace

Thema: Projektvorstellung: LocalizeMe (Typsichere Lokalisierung)
Am im Forum: Projekte

Ich schließe mich dem Feedback dazu an: Wo ist der Sinn?

Ich will die .NET-Lokalisierung nicht aufs Blut verteidigen, aber das Konzept hinter den RESX-Dateien, wie die Sprachen gesucht werden und die Tools dazu (RESX-Manager) sind schon sehr gut und ich wüsste nicht, was man da noch besser machen kann. Gerade der RESX-Manager macht das erst richtig wertvoll, da ich mit wenigen Klicks einfach die gesamte Lokalisierung als XLSX exportieren, zum Kunden/Übersetzer schicken und danach wieder importieren kann - quasi keine zusätzliche Arbeit für mich.

Also wenn Du etwas in die Richtung entwickeln möchtest und auch möchtest, dass andere davon profitieren (können), dann sollte ein wichtiges Ziel sein, genau diese bestehenden Tools möglichst gut zu unterstützen. Oder Du baust direkt darauf auf, z.B. indem Du einen eigenen Code-Generator schreibst, der das Problem, um das es dir hier geht, auf Basis der RESX-Dateien lösen kann.

Ich sehe hier also nur eines:
Ein Konzept, das extrem vom aktuellen bewähren Konzept abweicht und eigentlich nur genutzt wird, um eine klapprige Brücke zum bestehenden Konzept zu bauen.
Also auch, wenn deine Library ein reales Problem löst (ich sehe es auch noch nicht wirklich), dann hast Du immer noch das Problem, dass Du eine von Anfang an erzwungene Basis mit schleppst, die eigentlich niemand will.

Sorry, aber wenn ich ein konkretes Problem damit habe, dann baue ich die Lösung lieber direkt auf der erprobten Basis auf

Thema: Dependency Injection, wo schreibe ich allgemein gültigen Code
Am im Forum: Grundlagen von C#

By the way:


if (level != null)
    myLogger.SetLoggingLevel = level.Value;

Das solltest Du nicht machen
Generell nicht - das LogLevel gehört an die Methode übergeben.
Oder zumindest dieses Beispiel sollte das LogLevel immer manuell angeben, um Seiteneffekte zu vermeiden.

Oder was denkst Du passiert, wenn jemand in der Methode ein anderen LogLevel definiert?
Damit veränderst Du plötzlich auch alle Log-Aufrufe danach.

Thema: Dependency Injection, wo schreibe ich allgemein gültigen Code
Am im Forum: Grundlagen von C#

Das Problem, was Du hast, ist ein typisches Problem von dem Ansatz mit Contracts-Projekten: Du versuchst es überall zu verfolgen.
Ich würde es nicht überall erzwingen, sondern nur bei den Komponenten, die auch tatsächlich unabhängig vom Rest existieren können und für die es ggf. Erweiterungen oder andere Implementierungen geben kann oder soll. Beim Rest würde ich es einfacher halten und Abstraktion und Implementierung zusammen in einem Projekt lassen - letzteres als internal.
Logging wäre ein gutes Beispiel, wo sich Contracts anbietet, allerdings enthält das vermutlich kaum Logik (Du nutzt ja hoffentlich ein vorhandenes Framework), was diese Aufteilung wieder ziemlich überflüssig macht - deshalb würde ich das auch lassen.

In deinem Fall sehe ich zwei Wege, um deinen Code anzubieten:

  • Eigenes Logging-Interface, das eine entsprechende LogMethodExecution-Methode anbietet - da Du das Interface schon hast, bietet sich das ja an.
  • Eine Erweiterungsmethode, die die Methode an ein bestehendes Logging-Interface ergänzt.
    Das würde ich aber nur machen, wenn der Code darin einfach ist und vollständig auf Basis der Abstraktion (dem Logging-Interface) funktioniert - was bei dir auch der Fall ist.
    Und vor allem solltest Du es nicht übertreiben
  • Dein Weg - allerdings sehe ich da das Problem, dass es unauffällig ist, man kann es leichter vergessen. Eine Methode am Interface, das man sowieso nutzt, fällt mehr auf, als eine Klasse.
Und die Klasse würde ich einfach zur Abstraktion legen, sie ist ja auch Teil der Abstraktion, da sie eigentlich nur eine bestehende Abstraktion ohne eigene Logik aufruft.
Du hast also Logging-Interface oder Erweiterungsmethode in einem Projekt, die Methode Methode gibt deine Klasse zurück und die liegt ebenfalls im selben Projekt, wie die Abstraktion.

By the way: ggf. ist ein Struct besser, da das ja überall in jeder Methode genutzt wird, recht klein ist (enthält nur drei Referenzen, die sowieso auf den Stack geladen wurden) und nie länger lebt, als die Methode ausgeführt wird. So sparst Du dir ein Objekt pro Methode, das der GC aufräumen muss.
Und ich würde die Klasse/das Struct möglichst dumm halten, also kein Log im Konstruktor. Die LogMethodExecution-Methode ruft das EnterMethode auf und übergibt an die Klasse/das Struct nur alles nötige, um LeaveMethod aufrufen zu können.

Thema: Prüfen ob Anwenung schon läuft
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

Process (Docs)

Damit kanst Du die Anzahl Prozesse abrufen, nach TeamViewer suchen und wenn Du einen passenden Prozess findest, kannst Du Dinge tun.

Thema: Richtiges Binden von selektierten Listen an ein ListItem
Am im Forum: GUI: WPF und XAML

The ItemsControl - The complete WPF tutorial

Wobei das auch kein richtiges MVVM ist, weil das ViewModel fehlt.
Wie das richtig geht, steht in meinem letzten Link.

Thema: Richtiges Binden von selektierten Listen an ein ListItem
Am im Forum: GUI: WPF und XAML

Joa - Du bastelst dir alles selber, ohne DataBinding wirst Du keine Bindung hin bekommen.

Oder anders gesagt: Deinen Code kannst Du komplett entsorgen - so mies das auch klingen mag.
Bis auf das LINQ am Anfang (wobei das da auch nicht hin gehört, aber das ist ein anderes Thema) ist der komplette Rest ein MVVM-Verstoß und kann/sollte vollständig mit DataBinding, einem ItemsControl (oder ListBox) und ItemTemplate im XAML gelöst werden.

[Artikel] MVVM und DataBinding

Thema: Software zum Testen
Am im Forum: Smalltalk

Die Software hat eine Test-Version - probiere sie doch einfach aus?

Thema: Klasse T in generischer Methode instanziieren
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

Oder die Klasse bekommt ein Interface mit einer Methode, die Bool zurück gibt, dann klappt's auch ohne Reflection.

Thema: Klasse T in generischer Methode instanziieren
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

... oder Du schränkst den Typ entsprechend ein:


T Create<T>()
    where T: new()
{
    return new T();
}
Damit erschlägst Du dann auch gleich abstrakte Klassen, die Du so ja nicht nutzen kannst.

Übrigens klingt dein Vorhaben nach etwas, was man lieber anders lösen sollte

Z.B. würde ich sowas NIEMALS vom Namens abhängig machen, entweder der Name ist fix vorgegeben und dann kann ich auch ein Interface schreiben, oder ich versuche es möglichst zu vermeiden.
Und wenn es unbedingt doch machen muss, würde ich eher ein Attribut erstellen, nach dem ich dann suchen kann, dann ist der Name auch egal und im Attribut können noch ein paar Daten ergänzt werden.


Und MrSparkle war schneller

Thema: MemoryLeak "behebt" sich selbst durch Memory-Snapshot
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

Zitat von gfoidl
GC.Collect
bitte nur als Notlösung betrachten, da dies die interne Arbeit und Tuning vom GC durcheinander bringt.
Leider sehe ich aktuell keine andere Option (außer das manuell alles auf null setzen), der Zeitplan ist schon lange überschritten und der Kunde hat auch nur noch diesen Monat
Da sind mir Notlösungen lieber, als 2,5 GB im RAM versauern zu lassen und es soll im Anschluss sowieso weiter gehen, dann aber mit ruhigerem Zeitplan.
Zitat von gfoidl
PerfView ist mächtig, aber nicht trivial und intuitiv.
Wenn du willst und es gestattet ist, so kann ich mir die Dumps einmal anschauen und dann eine grobe Art Anleitung dazu erstellen.
Aber ich muss bei PerfView auch immer wieder "reinkommen", da ich es recht schnell wieder vergesse ;-)
Danke für das Angebot, aber das kann ich nicht alleine entscheiden
Ich spreche das bei nächster Gelegenheit mal an.

Kann aber gut sein, dass sich das um ein paar Wochen (oder sogar Monate) verschiebt, wenn die Notlösung soweit ausreicht, auch da kann ich nur meine Meinung zu sagen, aber nichts entscheiden.

Thema: MemoryLeak "behebt" sich selbst durch Memory-Snapshot
Am im Forum: Basistechnologien und allgemeine .NET-Klassen


private static async void TriggerDelayedFullGC()
{
    await Task.Delay(100, default).ConfigureAwait(false);

    GC.Collect();
    GC.WaitForPendingFinalizers();
    GC.Collect();
}

Das tut's auch.
So baue ich es erst einmal ein und schau später nochmal.

Thema: MemoryLeak "behebt" sich selbst durch Memory-Snapshot
Am im Forum: Basistechnologien und allgemeine .NET-Klassen


GC.Collect(GC.MaxGeneration);
GC.WaitForPendingFinalizers();
GC.Collect(GC.MaxGeneration);
Warum GC.MaxGeneration? Einfach weil viel hilft viel
Ich will erst einmal sehen, ob es überhaupt etwas bringt, danach schaue ich mir an, ob GC.MaxGeneration zu viel ist oder nicht.

Aber tatsächlich hilft es, aber anders als erwartet.
Ich beobachte jetzt zwei Dinge:
  • Die RAM-Auslastung geht ca. eine Sekunde (ich hab's mit dem Delay eingebaut) nach dem Verlassen des Dialogs wieder runter
  • Die Kurve ist nach den ersten ein/zwei Mal Dialog anzeigen und verlassen sehr viel gleichmäßiger, wie als würden Objekte gecacht werden, was ich aber nicht mache

Gerader der zweite Punkt verwundert mich - hast Du dazu eine Erklärung?
Das GC gibt bei jedem Mal Verlassen des Dialogs sehr viel weniger frei, als ich erwarten würde, aber beim erneuten anzeigen, wird auch sehr viel weniger benötigt.
Könnte das mit SQLite zusammenhängen, dass der - ähnlich dem SQLServer - anfängt, die Daten im RAM vorzuhalten, um den Zugriff zu optimieren?

Aber so wie das aussieht, übernehme ich das für alle Dialoge, dass nach jedem Dialog verlassen erst einmal aufgeräumt wird.
Ich teste nur noch, ob auch ohne GC.MaxGeneration ausreicht und das Delay kann vermutlich auch raus.
Ob das eine gute Lösung ist, weiß ich nicht, aber sie hilft und da ich etwas unter Druck stehe, ist es zumindest eine vorübergehend geeignete Lösung - denke ich.


PS:
Mit PerfView hab ich ein paar Dumbs erstellt, nur werde ich daraus nicht schlau.
Bisher kannte ich das Tool nicht und es scheint auch einiges an Einarbeitung zu benötigen, doch die Zeit habe ich leider nicht.
Ich würde daher eine schnelle Lösung bevorzugen, auch wenn es nur ein Flickenteppich ist, aber dann kann ich es später nochmal angehen.

Thema: MemoryLeak "behebt" sich selbst durch Memory-Snapshot
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

GC.MaxGeneration = 2
GCSettings.LatencyMode = Interactive

GC.Collect(GC.MaxGeneration) hat auch nichts gebracht.
Manchmal gibt er es auch von alleine frei, ich weiß allerdings nicht, wann und ob das die Daten vom aktuellen Dialog sind, den ich gerade verlasse, oder die von irgendwann vorher.
Wenn ich einen Button verwendet, um GC.Collect(GC.MaxGeneration) aufzurufen, gibt es meistens ungefähr die Menge frei, die ich erwarten würde.

Aber warum?

Ich hab jetzt folgendes eingebaut:


_ = Task.Delay(1000, default)
    .ContinueWith(_ => GC.Collect(GC.MaxGeneration), default(CancellationToken));
Das funktioniert so halb, es gibt ab dem zweiten Dialog-Verlassen wieder frei.

Ich schau mir jetzt PerfView an, vielleicht kann mir das ja etwas mehr verraten, vermutlich habe ich doch irgendwo ein gemeines Problem und ich jage hier unnötig dem GC hinterher.

Thema: MemoryLeak "behebt" sich selbst durch Memory-Snapshot
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

Zitat von gfoidl
Die meisten dieser Profiler führen eine kompletten GC durch (also inkl. Gen-2 und LOH) und haken sich in den Informationsstrom vom GC rein um so an die Ojekte zu kommen.
Genau dieses Verhalten hast du beobachtet.

Versuch dich einmal an PerfView, das bietet i.d.R. mehr Infos / Möglichkeiten. Aber die UX ist sehr bescheiden...
Das erklärt's ein bisschen, ich hab testweise nur ein einfaches GC.Collect gemacht, das geht vermutlich nicht weit genug?

Und danke für den Tipp - schau ich mir morgen an.
Zitat von Th69
Wenn durch den .NET Memory Profiler Speicher freigegeben wird, dann teste mal, ob auch ein GC.Collect (z.B. durch einen expliziten Button-Click) diesen freigibt.
Das hatte ich mir auch schon gedacht und GC.Collect eingefügt - allerdings nicht durch einen Button-Klick, sondern direkt nachdem alles weg geworfen wurde.
Gebracht hat es nichts, aber ich teste Morgen mal mit einem eigenen Button, vielleicht macht das einen Unterschied.
Zitat von Th69
erst wenn der Speicher an die Grenzen stößt, wird mehr freigegeben
Ich hätte nicht gedacht, dass er (in meinem Fall) knapp 3GB einfach so liegen lässt.
Aber gut, ich hab auch (noch) keine Ahnung, wie der genau arbeitet - das Buch liegt hier, aber die Zeit fehlt noch ^^

Thema: MemoryLeak "behebt" sich selbst durch Memory-Snapshot
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

Zitat von Th69
Kannst du nicht bei den "Detail"-Objekten die Referenz für das Hauptobjekt auf null setzen, sobald du das Hauptobjekt nicht mehr benötigst?
Ergebnis: Es liegt sehr viel weniger im RAM, weil ich jetzt alles auf null gesetzt habe, was ich nur finden konnte, durch alle Klassen hindurch.
Die Instanzen, die nicht da sein sollten, gibt's allerdings immer noch und ein Snapshot vom .NET Memory Profiler "beseitigt" die Instanzen immer noch.

Meine zweite Theorie war scheinbar erfolgreicher, aber auch nur manchmal und ein Snapshot vom .NET Memory Profiler "behebt" das Problem immer noch.
Aber gut, das heißt wohl, dass das Problem doch irgendwo in meinem Code liegt

Thema: MemoryLeak "behebt" sich selbst durch Memory-Snapshot
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

Da bin ich gerade dran, ist aber nicht "mal eben so" gemacht, weil der Kreis etwas größer ist.

Ich hatte gehofft, man kann dem GC einen ganzen Objekt-Baum mitgeben, zumindest erinnere ich mich, mal etwas davon gelesen zu haben.
Oder das war ein Issue, wo jemand nach genau so einem Feature gefragt hat.
Oder ich werfe irgendetwas anderes ganz durcheinander


Ich teste das Mal und eine andere Theorie, dann melde ich mich wieder.

Thema: MemoryLeak "behebt" sich selbst durch Memory-Snapshot
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

Guten Mittag,

es geht um eine WPF-Anwendung.
Ich suche gerade ein MemoryLeak, der scheinbar nur auftritt, wenn es um sehr viele Daten geht, also auch die Auswirkungen sehr groß sind.

Dabei ist mir aufgefallen, dass ich mit Hilfe der Diagnostic Tools von Visual Studio den Leak problemlos reproduzieren kann (mehrere Instanzen einer Klasse, wo nur eine sein sollte), doch sobald ich mit dem .NET Memory Profiler einen Snapshot erstelle, sind die überflüssigen Instanzen weg und der Speicher freigegeben.
Eventuell hängt das mit großen zirkulären Referenzen zusammen? Heißt: Ein "Haupt"-Objekt referenziert sehr viele "Detail"-Objekte, die auf das "Haupt"-Objekt verweisen.

Ich kann nicht ganz sagen, ob es wirklich keine Referenzen mehr gibt, daher die Frage:
Kann es sein, dass in einem Fall mit sehr vielen Objekte im "Referenz-Kreis" der GC nicht hinterher kommt und einfach zu lange braucht?
Und wenn ja, wie gehe ich damit am besten um, kann ich den Fall prüfen und ggf. ausschließen?

Und ist es möglich, dem GC die Objekte, die ich definitiv nicht mehr brauche, mitzugeben und sie so "löschen" zu lassen?

Thema: C# WPF Form öffnen
Am im Forum: GUI: WPF und XAML


var window = new MyWindow();
window.Show();

Zitat von Marc_Core
[...] Haupt Form
Zitat von Marc_Core
[...] über ein Click Event [...]
Was Du schreibst, schreit danach, dass Du versuchst, WPF so zu benutzen, wie man es bei WinForms gemacht hat.
Lass das bleiben, Du wirst nur Probleme damit haben.

Bei WPF arbeitet man mit MVVM: [Artikel] MVVM und DataBinding
Ich weiß aber auch, dass das beim Öffnen von einem Window nicht ganz so einfach ist - ist also nur als Hinweis gemeint.

Thema: Name des lokalen Administrators (Windows)
Am im Forum: Rund um die Programmierung

Zitat von Abt
PS: string statt String ist die sicherere Schreibweise (gilt auch für die anderen Varianten wie Int32 etc..).
Im Gegensatz zu Früher ist die klare Empfehlung nur noch die aliase (also die type keywords) zu verwenden.
Warum sicherer?
Ist doch beides äquivalent zueinander?

Thema: Problem bei Codierung zu UTF8
Am im Forum: Grundlagen von C#

Zitat von FZelle
System.Text.Encoding.Default passt meist viel besser.
... was seit .NET Core auch UTF8 ist:
https://docs.microsoft.com/en-us/dotnet/api/system.text.encoding.default?view=net-6.0#the-default-property-on-net-core

Thema: Implementierung von mehreren Interfaces bei Namenskollisionen
Am im Forum: Grundlagen von C#

Ich fasse Mal zusammen:

Du hast eine Klasse mit einem Konstruktor mit zwei Name-Parametern
In diesem Konstruktor erzeugst Du zwei weitere Instanzen von dieser Klasse ohne Parameter
Diesen Instanzen (je Cast auf ITest1 und ITest2) setzt Du die Namen aus dem jeweiligen Parameter
Der aktuellen Instanz setzt Du die zwei neuen Instanz-Variablen nameAlpha und nameBeta (das sind keine Properties) anhand der zuvor gesetzten Name-Properties
Die zuvor erstellten Instanzen verwirfst Du ungenutzt
Die beiden Name-Properties der aktuellen Instanz bleiben leer

Klingt das sinnvoll?
Für mich sieht das so aus, als versuchst Du Trial&Error irgendetwas zu erreichen, aber so funktioniert das nicht.
Du solltest dir entweder ein gutes Buch oder die Anleitungen von Microsoft dazu durchlesen, dann hast Du mehr Freude daran.

Ich vermute Mal, Du meinst folgendes:


class TestClass : ITest1, ITest2
{
    // DAS sind Properties - und halte dich an Namenskonventionen
    public string NameAlpha { get; set; }
    public string NameBeta { get; set; }

    string ITest1.Name
    {
        get { return NameAlpha; }
        set { NameAlpha = value; }
    }
    string ITest2.Name
    {
        get { return NameBeta; }
        set { NameBeta = value; }
    }

    public TestClass(string nameAlpha, string nameBeta)
    {
        NameAlpha = nameAlpha;
        NameBeta = nameBeta;
    }
}

Thema: Implementierung von mehreren Interfaces bei Namenskollisionen
Am im Forum: Grundlagen von C#

Stimmt
Ich schreibe meistens so:


var test1 = (ITest1)test;
var test2 = (ITest2)test;

Da braucht man das natürlich, aber das habe ich dann - der Klarheit wegen - nachträglich nochmal ergänzt.

Danke für die Korrektur

PS: Ich hab's oben aktualisiert.

Thema: Implementierung von mehreren Interfaces bei Namenskollisionen
Am im Forum: Grundlagen von C#


TestClass test = new TestClass();
Console.WriteLine(((ITest1)test).Name);
Console.WriteLine(((ITest2)test).Name);

// ITest1 test1 = (ITest1)test;
// ITest2 test2 = (ITest2)test;
// Hier brauchst Du den Cast nicht, das passiert automatisch (danke Abt, für die Korrektur)
ITest1 test1 = test;
ITest2 test2 = test;
Console.WriteLine(test1.Name);
Console.WriteLine(test2.Name);

Andere Wege gibt es nicht, zumindest keine, die nicht weit über jeden vernünftigen Nutzen hinaus gehen würden.
Und das Features heißt übrigens Explicit Interface Implementation

Thema: Wie kann man in Visual Studio zwei Projekte gleichzeitig starten?
Am im Forum: Grundlagen von C#

Hm - wusste ich nicht.

Deshalb sollte man es aber dennoch nicht so machen.
Das sollte wenn dann nur eine Not-Lösung für alle Projekte sein, für die es nicht anders geht.
Und ich bin mir ziemlich sicher, hier gibt es noch andere Optionen

Thema: Wie kann man in Visual Studio zwei Projekte gleichzeitig starten?
Am im Forum: Grundlagen von C#

Zitat
Console arbeitet auf Net 6.0 und die dll mit Framework 4.8.
Das ist dein Fehler.
Das mag funktionieren, ist aber mehr Zufall, weil dahinter der gleiche Byte-Code (IL) steht, aber beides sind verschiedene Frameworks und Du hast keine Garantie, dass es auch in Zukunft noch funktioniert.

Und nein, nur weil das eine Version 4.8 und das andere Version 6 ist, ist das nicht abwärtskompatibel, wie es bisher sonst immer war.
.NET 4.8 ist die letzte Version der "alten" Welt, alles danach ist von Grund auf erneuert und nicht abwärtskompatibel.

Wenn die DLL auch in einem anderen Projekt, das .NET 4.x sein muss (z.B. nicht Abhängigkeiten, die nicht aktualisiert werden können), dann setze die DLL mit .NET Standard 2.0 um, das wird von .NET 4.x und .NET 6 unterstützt.

Abt war so freundlich, das zusammenzufassen (hätte ich von Microsoft erwartet, aber naja):
[FAQ] Das .NET Ökosystem - .NET, .NET Core, .NET Standard, NuGet und Co

Und die Versionen-Tabelle von Microsoft:
.NET Standard-Versionen

Thema: Wie kann man in Visual Studio zwei Projekte gleichzeitig starten?
Am im Forum: Grundlagen von C#

Eigentlich sollte Visual Studio deine DLL automatisch kompilieren, wenn dein Konsolenprojekt sie braucht und sich darin auch etwas geändert hat.
Und das funktioniert auch ganz sicher, immerhin hast Du nur eine DLL, große Projekte haben 100(e) DLLs in einer Projektmappe Wenn das nicht funktionieren würde, wäre beim Visual Studio Team von Microsoft die Hölle los...

Du hast also irgendein anderes Problem, z.B. falsche Projekt-Referenzen.
Ich habe z.B. schon häufiger Referenzen gesehen, die die DLL im Output-Verzeichnis direkt referenzieren.
Das funktioniert, aber für Visual Studio ist das dann nur eine x-beliebige DLL ohne jede Projekt-Zugehörigkeit und kompiliert sie natürlich auch nicht automatisch.

Aber abgesehen davon:
Du kannst auch einen Rechtsklick auf jedes Projekt oder die Projektmappe machen und dort jedes Projekt oder die Projektmappe direkt kompilieren.

Thema: Async Task-Synchronisation
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

Naja, meine eigentliche Grundidee (und auch der Anwendungsfall, aus dem sie entstanden ist) sieht so aus, dass es mehrere Klassen gibt, die auf eine Ressource zugreifen.
Das Lock existiert also klassenübergreifend, z.B. statisch oder in einem Singleton.
Die einzelnen arbeitenden Klassen haben dann ihr Ticket jeweils pro Instanz und können somit erzwingen, dass nur diese eine Instanz etwas tun darf, bis sie selber fertig sind.

Nun kann es aber sein, dass die arbeitende Instanz aus irgendeinem Grund (das wäre definitiv ein Bug) nicht mehr existiert, das Lock vorher aber nicht korrekt freigegeben wurde.
In diesem Fall würde das Lock dann auf ewig gesperrt bleiben, weil niemand mehr eine Referenz auf das Ticket hat - also ein Deadlock.
Durch die WeakReference würde dieser Deadlock irgendwann (indirekt durch den GC) wieder freigegeben werden.

Thema: Async Task-Synchronisation
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

Zitat von gfoidl
Diesen Fall würde ich als "undefiniert" für die Synchronisation sehen und daher eine NullReferenceException werfen. "Fail early" ist ein gutes Paradigma, denn so kann unterschieden werden ob tatsächlich null übergeben wurde od. ob der lock einfach nicht betreten werden kann.
Stimmt - ja, ich versuche möglichst ohne Exceptions zu arbeiten, wo es nicht notwendig ist (z.B. bei Try-Methoden), aber hier ist es ja inhaltlich und dank nullable reference types offensichtlich, dass kein null übergeben werden darf.
Außerdem behandle ich das Disposed genauso: Es fliegt eine Exception für einen Fall, der "eigentlich" nicht vorkommen darf.

Thema: ClickOnce: MethodAccessException beim Start
Am im Forum: Entwicklungs- und Laufzeitumgebung (Infrastruktur)

Das konkrete Problem hatte ich nicht mehr gelöst - zumindest soweit ich mich erinnere.
Ich weiß jedenfalls noch, dass ich nach einem ClickOnce-Problem (nicht das erste) mich dazu entschlossen habe, ClickOnce als Problem-Zeit-Fresser ganz abzuschaffen und habe dann auf Basis von AutoUpdater.NET eine Alternative eingeführt.

Ob das für dich auch der richtige Weg ist, kann ich dir nicht sagen, dazu bin ich zu lange aus dem Thema raus.
Du solltest dir aber in jedem Fall gut überlegen, bevor Du ganz umstellst, denn das bedeutet zwar weniger Probleme, allerdings machst Du gleichzeitig einiges an anderen Aufwänden und möglichen Problemen auf, die Du vermutlich gar nicht auf dem Schirm hast.

Bei uns war es eine Folge von mehreren Problemen, die jedes Mal viel Zeit gekostet haben und dass wir generell (auch aus anderen Gründen) nie ganz zufrieden mit ClickOnce waren.