Wenn das wirklich so "simpel" ist, dann erinnert mich das ein wenig an den Greedy Algo, auch wenns vielleicht nicht 100% passt - ist aber recht beliebt bei simplen Scheduling Implementierungen.
Für boolsches Scheduling im Maschinenbau hab ich auch schon mal den Constraint-Satisfaction Solver angewandt, der auch ein wenig in die Richtung geht wenn es komplexer wird. Google hat da ne recht nette Seite für https://developers.google.com/optimization und auch nen NuGet Package https://www.nuget.org/packages/Google.OrTools
Bitte immer relevanten Code zeigen, siehe auch Wie post ich richtig?
Beides geht seit der Umstellung auf .Net8 leider nicht mehr.
Es gab keine Features Changes mit .NET 8, die mit dem Icon zusammen hängen würden. Wird also eher an Deinem Resource Handling liegen.
Es gibt zwar keine offizielle Unterstützung von Base23 in .NET - aber auf GitHub finde ich sehr sehr viele Beispielimplementierungen. Passt da nicht eine?
Die sehen auch mit entsprechenden Bit-Operations deutlich effizienter aus; mach halt mal ein Benchmark.
Was genau meinst Du mit Skalierbarkeit? Auf mehrere Threads würde das eh kein Sinn macht, weil die Threadverwaltung vermutlich mehr Power kosten würde als Du Skalierungsbenefits hättest. Und wenn dann eh Tasks statt Threads 😉
WPF ist so konzipiert, dass MVVM verwendet wird. Du wirst dutzende von Workarounds brauchen, wenn Du MVVM nicht verwenden willst; das ist nicht zu empfehlen. Vor allem braucht man oft mehr Zeit das später richtig zu migrieren, als es gleich richtig zu starten.
Ja, das macht die Einstiegshürde von WPF relativ hoch - ist aber leider so.
Danke für die Links, ich habe heute morgen in der Forensuche immer "Kein Ergebnis" angezeigt bekommen.
Danke für den Hinweis, vielleicht hab ich neulich was kaputt-optimiert...
Zur Thematik async/await, ich werde den Task wohl besser in einem eigenen Thread umsetzen, da ich beim empfangen ein Event auslösen will und nicht auf eine Rückgabe der Methode warten will. Somit würde await rausfallen, da die Abfrage nach neuen Nachrichten ja kontinuierlich in der while Schleife läuft und nicht beendet wird.
Ich seh jetzt weiterhin kein Grund, dass Du den Thread brauchst (ohne keinen ganzen Kontext zu kennen) - außer Du willst das Gesamtkonstrukut auslagern; und auch das geht simpler mit einem Long-Running Task.
Aber trotzdem hast Du ein asynchrones Verhalten, zB allein durch AcceptTcpClientAsync. Und dann hast nen extra Task, mit dem Du asynchron arbeiten kannst.
Ich versuche momentan alles Lokal auf dem Rechner über die 127.0.0.1. Firewall sollte dann normal ja kein Thema sein, oder?
In Deinem Code arbeitest Du aber mit IPAddress.Any und nicht mit IPAddress.Loopback - und nur Loopback geht nicht über die Firewall. Any schon. Any ist nicht 127.0.0.1 sondern "*", also alles.
Verwendest vielleicht ein Port, den Du nicht verwenden darfst?Sowas wie 5000 is fine, alles unter 1024 ist reserviert / blockiert.
Ich hab mir dazu kurz zwei Demo Konsolen gebaut:
Server
int port = 5000;
IPAddress localAddr = IPAddress.Loopback;
TcpListener server = new(localAddr, port);
try
{
server.Start();
Console.WriteLine($"Server gestartet und hört auf {localAddr}:{port}...");
while (true)
{
Console.WriteLine("Warte auf eine Verbindung...");
TcpClient client = await server.AcceptTcpClientAsync();
Console.WriteLine("Ein Client wurde verbunden.");
// Lese Daten vom Client
NetworkStream stream = client.GetStream();
byte[] buffer = new byte[1024];
int bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);
string dataReceived = Encoding.UTF8.GetString(buffer, 0, bytesRead);
Console.WriteLine($"Empfangen: {dataReceived}");
// Antwort zurück an den Client senden
string response = "Hallo, Client!";
byte[] responseData = Encoding.UTF8.GetBytes(response);
await stream.WriteAsync(responseData, 0, responseData.Length);
Console.WriteLine("Antwort gesendet.");
// Verbindung schließen
client.Close();
}
}
catch (Exception e)
{
Console.WriteLine($"Fehler: {e.Message}");
}
finally
{
server.Stop();
}
Client
IPAddress server = IPAddress.Loopback;
int port = 5000;
try
{
TcpClient client = new(server.ToString(), port);
Console.WriteLine($"Verbunden mit dem Server auf {server}:{port}");
// Nachricht an den Server senden
string message = "Hallo, Server!";
byte[] data = Encoding.UTF8.GetBytes(message);
NetworkStream stream = client.GetStream();
await stream.WriteAsync(data, 0, data.Length);
Console.WriteLine($"Gesendet: {message}");
// Antwort vom Server lesen
byte[] buffer = new byte[1024];
int bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);
string response = Encoding.UTF8.GetString(buffer, 0, bytesRead);
Console.WriteLine($"Antwort vom Server: {response}");
// Verbindung schließen
client.Close();
}
catch (Exception e)
{
Console.WriteLine($"Fehler: {e.Message}");
}
Output:
// Server
Server gestartet und hört auf 127.0.0.1:5000...
Warte auf eine Verbindung...
Ein Client wurde verbunden.
Empfangen: Hallo, Server!
Antwort gesendet.
Warte auf eine Verbindung...
// Client
Verbunden mit dem Server auf 127.0.0.1:5000
Gesendet: Hallo, Server!
Antwort vom Server: Hallo, Client!
PS: TCP Handling als Lernaufgabe ist gut; man sollte wissen, wie das alles funktioniert. Soll das jedoch ne produktive Sache werden, dann sollte man nicht das Rad neu erfinden und auf sowas wie HTTP APIs oder gRPC setzen.
Die häufigste Ursache bei der IOException (mal abgesehen, dass Client etc nicht gestartet ist..) beim Verbindungsaufbau ist die Firewall. Geht die Connection durch eine Firewall, hast entsprechend die Incoming (Server) und Outgoing (Client) Regeln gesetzt?
Entsprechend viele Treffer findet man bei der Suche
=> https://mycsharp.de/forum/threads/95484/tcplistener-an-established-connection-was-aborted-by-the-software-in-your-host-machine
=> https://mycsharp.de/forum/threads/15768/faq-tcpclient-einfaches-beispiel
=> https://mycsharp.de/forum/threads/19670/tutorial-client-server-komponente-ueber-tcp-sockets
=> https://learn.microsoft.com/en-us/dotnet/fundamentals/networking/sockets/tcp-classes
PS: Du solltest async/await korrekt umsetzen, so ist das nix. Das kann und wird ansonsten weitere (nicht dieser) Fehler verursachen.
SSL wird Global in der Klasse gesetzt. Kann es sein, das diese Globale Einstellung nach eienr gewissen Zeit verloren geht?
Nein, kann nicht sein.
Aber die WebRequest-Klasse ist seit >10 Jahren veraltet; verwende den HttpClient. Beachte auch die Hinweise in der Doku, wie
HttpClient is intended to be instantiated once and re-used throughout the life of an application. Instantiating an HttpClient class for every request will exhaust the number of sockets available under heavy loads. This will result in SocketException errors.
Und verwende asynchrone Programmierung bei sowas. Das ist essentiell.
Mir is nich klar, was Du für eine Antwort Du Dir wünscht.. aber ich nehm mal kein Blatt vor den Mund 😃
Es ist klassischer Spaghetti-Code, aber denke, dass Dir das bewusst ist 😉
Wie man es machen würde:
string
und nicht String
, ausser Du willst die Eigenschaften von String haben (zB Überschreibbarkeit)Die Community Version hat den gleichen Basis-Funktionsumfang wie Professional. Du musst wie in vielen Fällen aber hier eine Pay-Variante nehmen, sobald Du eine gewisse Firmengröße erreichst.
Enterprise organizations are defined as >250 PCs or > $1 Million US Dollars in annual revenue.
Es dient also letzten Endes Einsteigern, Studenten, (sehr)kleinen Firmen, Freiberuflern... in die Microsoft Welt einzutauchen.
Siehe offizieller Vergleich: Compare Visual Studio 2022 Editions
Ich verwende Enterprise (ich bekomm sie von Microsoft gestellt) und für den Alltagsentwickler lohnt sich das nicht.
Live Unit Testing, Code Coverage sind aber echt tolle Features.
Willst Du gern etwas Geld los werden, einfach als Inspiration: https://www.betterplace.org/de 😃
Muss auch nicht installiert sein, wenn man die Self Contained Variante als Deployment nimmt. Ist also zwangsweise kein Fehler..
Aber... steht im Link...
Hab ich wohl falsch in Erinnerung gehabt.
Zeitplan: Microsoft will Enterprise-Kunden 2026 auf neues Outlook umstellen
Die automatische Umstellung erfolgt aber im April 2026, mit der Option zurück zu gehen.
Zitat von fichz
Gibt es generell Infos, wann das neue Outlook kommen wird?
Das ist schon da. Mail und Calendar App auf Windows 11 sind zum 31. Dezember 2024 abgekündigt; ab da das neue Outlook (für alle, die bisher Mail genutzt haben).
Für Business Kunden ist das Ende - laut verschiedener News - vom "Outlook Legacy" der 31. März 2026.
Zitat von fichz
Aber gibt es einen Richtwert ab wann man von "Massensenden" spricht?
Interpretation der großen Anbieter ist: alles, was automatisiert ist.
Das Exchange-Limit bei Microsoft, das sich auf den Graph im Userkontext auswirkt, sind 30 Nachrichten pro Minute und ein Recipient Limit von 10.000.
Das hört sich erstmal viel an, aber die Limits sind mit entsprechenden Automatismen (zB ERP) schnell erreicht. Klar, für Mini-Dinge mag das reichen, man sollte es aber im Hinterkopf haben.
Ja das ist ziemlich "bescheiden", dass es aktuell nicht zur Verfügung gestellt wird. Kann man halt nur hoffen, dass dies vielleicht noch kommt.
Muss kommen. Die Kritik am neuen Outlook is so groß, bricht so viele Prozesse- hat schon sein Grund, wieso das schon 2 mal verschoben wurde, alle aufs neue Outlook zu zwingen.
Es geht auch erst seit kurzem, dass man ein Postfach verbinden kann, das keine Outlook-Lizenz hinterlegt hat, wie es sonst immer der Fall und bei vielen Firmen war (aufgrund der verschiedenen Lizenzierungsmodelle).
Wäre das ein Add-In für das Outlook New, welches ich dann irgendwie ansprechen kann?
Du kannst basierend auf JavaScript, das ja COM-Addins ersetzt hat, Office Addins schreiben und über die O365 Admin Konsole entsprechend als internes/private Addin verteilen. In dem Addin selbst kannst dann zB Textfelder anzeigen, die der User ausfüllen soll und die Mail anschließend via makeEwsRequestAsync senden.
Das ist dann nicht der "echte" Office Editor, dann arbeitest mit Templates. Alternativ kannst mit dem Addin auch nen API-Request an einen Service von Dir schicken, dort das E-Mail Template aufbauen und dann via Graph/ACS verschicken.
Das war zumindest meine/unsere Evaluierung.
X-Unsent 1 wird einfach im neuen Outlook (noch/mit Absicht?) nicht unterstützt/vergessen.
Für das Versenden im Hintergrund verwende ich nun die Graph API (welche man meines Wissens ja aktuell verwenden sollte), welche super funktioniert. Somit wäre das erste Problem beseitigt.
Das war eigentlich immer nur ein Workaround. Aber zugegeben ist das der einzige Workaround, den man im Kontext des Users aktuell immer noch machen kann. Es war aber nie für das Massensenden gedacht, deswegen auch die sehr harten Limits, die evtl auch gesenkt werden sollen. Für Massenversand ist der Azure Communication Service gedacht.
- Gibt hierzu irgendwelche "Best Practices"?
Nicht von Seite Microsoft.
- Wie macht ihr es sonst?
Hintergrundmails immer über die entsprechenden APIs ohne Desktop-Anwendung.
Für Outlook New gibt es derzeit keine Lösung es als Editor vor dem Absenden, wie man es bisher von Outlook gewohnt war, zu automatisieren; ich hab das mal vor einiger Zeit aufgrund eines Projekts recherchiert, und nur Hacks gefunden, die zu dem Zeitpunkt auch nicht mehr funktioniert haben.
Eine relativ einfache Option ist es aber ein Outlook Add-In zu schreiben, sodass der User so eine Quasi-Editor-Funktion in Outlook hat.
Ein Hinweis: in fast jeder Runtime-Technologie gibt es einen Standard, die man loggt. In .NET ist das das ILogger-Interface.
Docs: Logging in C# and .NET
Hier selbst was zu erfinden, ist fast immer der schlechteste Weg.
Das ILogger Interface ist unabhängig und standardisiert, sodass verschiedene "Log Consumer" angehängt werden können.
Der Stelle, an der Du loggst soll egal sein, wohin das Log später geschrieben wird. Du kannst dann zB das sehr verbreitete Serilog als Log-Provider verwenden, das dann in verschiedene Sinks schreiben kann.
Willst Du das Log selbst konsumieren in Deiner App, dann würdest Du eine ILoggerFactory erstellen, und dann in Deiner GUI darauf hören.
Wenn die Klasse der Instanz, zu der die Property gehört, keine Implementierung über eine aktive Benachrichtigung bei Änderung hat (zB ein Event), dann musst das eben die ganze Zeit periodisch abfragen, zB mit Hilfe eines PeriodicTimers.
Eine DLL kann nicht einfach so eine Property irgendwo im luftleeren Raum haben.
Die Property muss ja irgendwie Teil einer Instanz einer Klasse o.ä. sein...? Magst den genauen Kontext erklären?
Zitat von RiekeSeidl66
wofür auch immer dieses "internal" gut ist???
Weil es genug Situationen gibt, wo internal offensichtlich unabdingbar ist...
.. und dutzende weitere nützliche Fälle von internal. Feel free to google 😉
Hi, zunächst die Bitte Deinen Code in Zukunft in die Code Tags zu setzen, das ist echt nicht so schwer und erleichtert allen das Lesen.
Zu allen CS Fehlern gibt es einen Dokueintrag, der zeigt, wodurch der Fehler ausgelöst wird, in Deinem Fall eben CS0051.
// CS0051.cs
public class A
{
// Try making B public since F is public
// B is implicitly private here.
class B
{
}
public static void F(B b) // CS0051
{
}
public static void Main()
{
}
}
Wie Du hier auch am Kommentar siehst, wird am Konstruktor von "F" der Parameter "B" erwartet.
"B" ist aber eine private Sub-Klasse von A, und kann daher nicht als Public-Parameter verwendet werden.
Bei Dir wird das der gleiche oder ein ähnlicher Fall sein. Ich rate mal, weil Du den Code nicht zeigst: Deine Klasse Datenklasse ist private, aber ein Parameter einer Public-Methode einer Public-Klasse - das geht nicht.
Ansonsten beachte die Hinweise von Th69:
Unwahrscheinlich, dass das so spezifisch konfigurierbar ist - das ganze Spell Feature in VS ist nur sehr rudimentär implementiert. Es gibt auch sehr viele False-Positives, sodass Du nen Kringel bekommst, obwohl es nen Code-Wort ist (zB viele typeof Situationen).
Nur als Hint: ich selbst, wenn ich VS Onboardings mit Leuten mache, empfehle direkt als einen der ersten Schritte den Spell Check zu deaktivieren, weil er enorm viel Editor-Performance kostet. Je mehr offene Code Tabs, desto mehr merkt man das, zB ab der Responsiveness von IntelliSense.
Es gibt dazu eine Severity Einstellung
Was ist denn Deine konkrete Frage?
So kann man völlig trocken mit "in C# macht man Abstraktionen meistens mit Interfaces" antworten.
Felder haben auf alle Fälle eine Eigenheit bei Unity im Editor.
Das ist leider ein bekannter Bug, siehe [Preview 4] White line on the left of the window that vanishes once the window is resized
#4176
Zitat von FrankenDerStein
Und JA ich bin ein fan von der empirischen Vorgehensweise, normal komme ich damit super zurecht, aber ausnahmen gibt es natürlich immer.
Mit Try and Error versteht man in der Regel jedoch kein Konzept; weswegen das bei Dingen, bei denen man eben diese Konzepte verstehen muss, zu 99,9% nach Hinten los geht 😃
Eine der maßgeblichen Gründe, wieso zB Leute massive und fatale Fehler bei Auth-Systemen machen.
Aber so oder so finde ich das die Googles Entwickler Konsole weniger übersichtlich und verständlich ist als Microsoft Azure Entwicklerkonsole.
Geschmackssache. Bin auch ein Fan der Azure Console gegenüber Google Cloud/Google Produkten.. aber was Microsoft sich bei der UI Aktualisierung von Azure Gedacht hab (die neuen Panes), macht vieles komplizierter und man braucht viel mehr Klicks.
Am Ende: Geschmackssache.
Also folgendes Problem ( in Unity3d, ist aber nebensächlich wo ).
Leider nicht ganz. Unity verwendet zwar C#, aber hier muss man leider relativ oft Dinge anders machen oder mit Workarounds arbeiten. Auch ist die C# Version in Unity alt; aktuell C#9 und auch mit einem abgespeckten Feature-Set.
Während/Nach dem Drama rund um Unity, weswegen dann auch der CEO Riccitiello gehen musste, sind viele Unity Entwickler zu Godot gewechselt, das ebenfalls .NET unter der Haube anbietet und viel moderner ist.
Ich würde nun etwas raten und behaupten, dass Du bisschen nach Try and Error vorgehst 😃 Les Dir die Basics der Google API Docs durch, da steht eigentlich alles, was man beachten und aktivieren muss. Ich verwend die Google API Docs für Einsteiger-Samples weil das eigentlich echt alles sehr sehr gut dokumentiert ist.
Zu Deinem Problem.
Das ist eine API, die OAuth als Authorisierung verwendet; Du musst also bei der Authorisierung die entsprechenden Scopes mitgeben.
Beim ersten Zugriff des Users auf ein Features Deiner App wird dann auch ein Consent-Screen angezeigt, in dem der User den Zugriff auf die Scopes erlauben muss.
Google ich nach der englischen Variante Deiner deutschen Fehlermeldung, dann scheinst Du irgendwas bei Deiner API Registrierung vergessen zu haben, zB hast Du vergessen anzugeben, auf was Du zugreifen willst. In der Google Trefferliste sieht man entsprechende Probleme mit Calendar API und Maps API, wo genau das nicht getan wurde.
Zitat von perlfred
Hallo Abt!
Für meine Begriffe ist die Referenz auf die Eigenschaft DVD (vom Type DVDEintrag) des ViewModels (welche an die View gebunden wird) geblieben.
Edit: Okay, wenn der DVDEintrag gar nicht das Viewmodel ist, dann ist das was anderes; das war für mich jetzt so nicht ersichtlich / hab ich übersehen.
Sollen Sub-Eigenschaften Deines Datenmodells über Bindings ansprechbar sein, dann musst Du die ebenfalls in die ViewModel-Hierarchie übernehmen. Vermutlich kommt daher zuerst mein Missverständnis, dass Du eben nur nen Teil als Binding eingebunden hast.
Wenn DVDEintrag ein "Business/"Daten"-Modell ist, dann kann es für komplexe Bindings nicht verwenden werden, da es keinerlei Change-Information (über INotifyPropertyChanged ) liefern kann.
Du brauchst dann für jede Eigenschaft von DVDEintrag auch eine bindbare Eigenschaft im ViewModel.
Vereinfacht:
public DVDEintrag DVD
{
get =>_DVD;
set
{
_DVD = value;
OnChanged(nameof(DVD));
}
}
public DVDAblage Ablage
{
get =>_DVD.Ablage;
set
{
_DVD.Ablage = value;
OnChanged(nameof(DVD.Ablage));
OnChanged(nameof(DVD));
}
}
Das ist trotzdem kein MVVM, was Du da machst - und kein Binding.
Du verwendest nun halt Events und setzt die manuell.
Bindings basieren auf der Referenz, die beim Erzeugen der View existiert. Ein Clone erzeugt eine neue Referenz, die dem Binding nicht bekannt ist - daher funktioniert natürlich auch nichts. Clone gilt bei Bindungen allgemein als Bad Practise.
Willst Du das unbedingt über Clones lösen, musst Du das Binding manuell ersetzen / neu setzen.
Das Visual Studio Tool (ist ja auch nur eines von vielen), hat ein Längenlimit. Ist die XML zu groß, kommt Schmarrn raus.
Das is im Endeffekt ganz schöner Spaghetti-Code.
Das grundlegende Problem ist, dass Du alles im UI-Thread ausführst. Du blockierst damit die gesamte UI-Interaktion und alles, was dazugehört. Besonders das while(!ProgResult)
ist dafür schuld.
[FAQ] Warum blockiert mein GUI?
Der ganze Code hat aber ohnehin in der UI sowieso nichts zu suchen ([Artikel] Drei-Schichten-Architektur). Du musst also alles auslagern in einen eigenen Task; und nicht nur das ReadLine
. Im Endeffekt sogar 2 Tasks.
Mach Dir also eine saubere Klasse zur Kommunikation, und arbeite zB mit Events für UI-Infos statt das alles so zu verwursteln.
Cache-Dateien löschen (.vs
Ordner und alle bin/obj
Ordner); evtl auch potentiell vorhandene .suo
/.user
Files.
Wenn Du Extension nutzt können die ebenfalls für sowas verantwortlich sein.
Auf Windows 10? Meiner Recherche nach (vor ein paar Monaten bei einer Anfrage) leider normal.
Die Rounded-Corner API für Top-Level Windows Apps gibts erst in Windows 11.
ObservableCollection<MyType> list = new();
da ich dies intuitiver zu lesen finde.
Nicht nur das, sondern weil [] auch einfach einen anderen Typ erzeugen kann.
Beispiel:
Bei EF Core ist strikt empfohlen alle Relationen als HashSet zu definieren.
public ICollection<MyEntity> MyEntities { get; set; } = new HashSet<MyEntity>();
Würde man hier mit []
arbeiten, würde eine List<MyEntity>
initialisiert werden, was eine völlig andere Wirkung auf die Arbeistweise von EF Core hat - ein Fehler, der in sehr bösen Race Conditions / Komplikationen enden kann.
[] ist echt nett, aber teilweise eine böse Falle.
Die bessere Idee sind eigentlich Bindings, spricht Du hälst die Daten in einem State und die UI rendert die State.
Was Du machst ist die UI als "Speicher" zu missbrauchen. Das macht sehr viel sehr umständlich.
Du sprichst zwar von der DrawAppointmentsForFreshMonth Methode, Du verwendest sie auch, aber Du hast im Code die Methode nirgends hinterlegt. Da wir keine Glaskugel haben, solltest Du den Inhalt der Methode schon zeigen, sonst machts kein Sinn.
Ob Du Methode aufgerufen wird, kannst Du selbst mit dem Debugger testen.
[Artikel] Debugger: Wie verwende ich den von Visual Studio?
PS: Dein Code ist sehr sehr umständlich und wenn man als Aussenstehender drauf schaut, weiß man nicht wirklich warum Du was tust.
Wenn Du wirklich noch C# 7.3 verwendest; das ist weit über 6 Jahre alt und Du verwendest eine .NET Version, die uralt ist.
[FAQ] Das .NET Ökosystem - .NET, .NET Core, .NET Standard, NuGet und Co
Der erste Abruf der CPU Werte sind immer 0 - und Du erstellst die ganze Zeit den Counter neu. Daher kann auch immer nur 0 heraus kommen.
If the calculated value of a counter depends on two counter reads, the first read operation returns 0.0.
Mit
static void Main(string[] args)
{
PerformanceCounter cpuCounter = new("Processor", "% Processor Time", "_Total");
while (true)
{
Console.WriteLine(cpuCounter.NextValue());
}
}
funktioniert alles einwandfrei.
Dein gesamter Code is aber nich wirklich stabil. Verwende einen PeriodicTimer statt einer Endlosschleife mit einem Thread.Sleep.
zB
static async Task Main(string[] args)
{
CancellationToken token = new(); // optional externes Canceln oder nach Zeit etc.
PerformanceCounter cpuCounter = new("Processor", "% Processor Time", "_Total");
using PeriodicTimer timer = new(TimeSpan.FromSeconds(1));
while (await timer.WaitForNextTickAsync(token) && !token.IsCancellationRequested)
{
Console.WriteLine(cpuCounter.NextValue());
}
}
Zitat von jogibear9988
Muss ich den die Skia und HarfBuzz libs immer mitliefern, oder werden dort auch die auf dem System (wenn vorhanden) existierenden benutzt?
Es gibt kein GAC wie in .NET Framework mehr - Du musst immer alles mitliefern (außer die Runtime, die kann optional mitgeliefert werden). Spielt die Größe eine sehr wichtige Rolle, dann kannst Du evtl Trimming anwenden. Die Build-Zeiten werden dadurch jedoch (irgendwo musses ja her kommen) deutlich erhöht.
Zitat von Palladin007
Das verstehe ich nicht? Angenommen, der ThreadPool würde nicht statisch arbeiten, sondern alle Threads je Instanz verwalten, wo ist dann das Sicherheitsrisiko?
Ich hatte in Erinnerung, dass es einen generellen Security Flaw gibt, wenn eigene Thread Pools abgeleitet werden können aufgrund der Implementierungsart, aber das scheint nur (noch?) für UnsafeQueueUserWorkItem Code Access Security bei zu gelten, siehe Remarks.
Das sieht aus, als würde da etwas fehlen? 😃
Hups. Kommt davon wenn man nebenher aufgefordert wird "mal kurz" was zu machen...
Ich sehe generell beim Drüberschauen keine große Lücke, auf Anhieb.
Zitat von Palladin007
schade, dass der .NET-ThreadPool komplett statisch arbeitet und ich mir keine eigene Instanz bauen kann 😕
Der ThreadPool ist im Endeffekt nichts anderes als eine Implementierung des TaskScheduler auf einer eigenen Ebene. Davon eine eigene Instanz zu erzeugen ist ein potentielles Sicherheitsrisiko. Daher soll der ThreadPool auch nicht verwendet werden, wenn Du sicherheitsrelevante Aufgaben hast und Dein ausführende System keine Zugriffssicherheit des ThreadPools bietet (Du zB das System mit anderen Anwendungen auf der Ebene teilst).
Deine Implementierung SingleThreadTaskScheduler ist also quasi ein Custom Thread Pool. Ich sehe
Kurze Frage zur Problemstellung:
Sind die Aufgaben in den Tasks, auf die Du wartest, identisch?
Also Fragen mehrere Requests zB an was "1+1" ist und Du hast dann ein externen Call, der die "2" liefert?
Kannst Du dann nicht die Anfrage zusammen mit dem Task in einem Dict halten, sodass gar kein zweiter Task erzeugt wird, der nochmal "1+1" beinhaltet, sondern Du hast ja dann den Task schon auf den Du wartest?
e.g. dict.Add("1+1", myTask);
Dann hättest Du die Race-Condition weg-optimiert.
HolidayClient ist in Nager.Date unbekannt; existiert nicht. Erkennt man wenn man einfach die Repository-Suche verwendet.
Kann das sein, dass Du https://github.com/nager/Nager.Holiday meinst? Zumindest spuckt das Google aus wenn man nach nager holidayclient sucht.
Das is ein anderes Projekt, ein anderes Paket und ein anderer Namespace.
Aber habe ich damit nicht immer noch das Problem, dass ein Deadlock auftreten kann, wenn alle ThreadPool-Threads die Ausführung je eines Tasks mit UnsafeQueueUserWorkItem in die ThreadPool-Queue legen, die aber nie ausgeführt werden, weil alle ThreadPool-Threads darauf warten?
Ja, aber das ist ja ein grundlegendes Problem des Henne-Ei Prinzips.
Aber mit
Der betreffende Code kann sehr oft gleichzeitig laufen, also z.B. sehr viele Nutzer, die ein bestimmtes Datum abwarten und dann alle auf einmal los rennen, Requests produzieren und ThreadPool-Threads füllen. Die Requests laufen auch recht lange, es kann also durchaus sein
gehst Du ja bewusst dieses Risiko ein. Daher skaliert man ja zB Ticket-Sale-Systeme auch nicht über diese Art und Weise. Das ist im Endeffekt ja nichts anderes als ein DoS gegen sich selbst.
Der Standard-ThreadPool bei WIn32 hat 1023 Worker und 1000 für async I/O. Musst halt das Erstellen limitieren / extern skalieren. Aber das wäre auch ohne den Pool der Fall, sprich bei manuellem Handling.
Der ThreadPool is nen sehr komplexes und schlaues Konstrukt; vielleicht kann er das ein oder andere auch erkennen. Aber für Long-Running IO ist eigentlich der ThreadPool das falsche Mittel bzw. ist das eigentlich nicht seine beste Stärke. In Deinem Fall is eventuell doch eigenes Management statt Pool der bessere Weg.
Ich hab nen bisschen rum probiert, aber keine funktionierende Lösung in meinem Zeitblock gefunden.
Aber eigentlich bin ich der Meinung, dass das mit Thread.QueueUserWorkItem bzw. Thread.UnsafeQueueUserWorkItem funktionieren müsste.
.GetAwaiter().GetResult() ist Wait() auf reines await-Replacement prinzipiell vorzuziehen, weil zB potentielle Exceptions innerhalb eines Wait() ansonsten zu einem Deadlock führen kann.
Jedoch kann .GetAwaiter().GetResult() in ganz gewissen Szenarien immer noch zu Deadlocks führen. Umgekehrt ausgedrückt gibt es nur ganz arg wenige Szenarien, die überhaupt Deadlock-frei auf Tasks "warten" können.
Nur der Vollständigkeit halber: hab aktuell keine vollständige Lösung auf Deine Frage.
Zitat von Joe78
Bekomme zwar ein Bild auch über ShellExecuteEx geöffnet, aber der Windows Bildbetrachter lässt mich mit den Pfeiltasten auch hier nicht weiter navigieren.
Das is nen bekannter Bug in der App, leider seit Jahren. Der is besonders zu merken, wenn man durch nen OneDrive Ordner navigiert, und die Bilder dynamisch nachgeladen werden. Man muss dann nicht immer, aber oft die App neu starten, ansonsten erkennt werden die neuen/nachgeladenen Bilder nicht erkannt.
Wird wohl nie gefixt werden.
Was soll das denn am Ende werden, oder vereinfachen? Und welche UI Technologie ist das? Forms?
In quasi allen modernen UIs würde man Bindings verwenden - da braucht man das alles nicht.
Wenn ich mir grob denken kann, dass es hier um Lokalisierung geht wäre ich überrascht, dass Du die Anforderungen hast, dass Du was völlig Neues erfinden müsstest.
Wenn Du nur den Source haben willst, dann nimm einfach den HttpClient; da sind auch dutzende Beispiele in den MS Docs.
WebView2 is wenn Du einen Browser nachahmen willst, zB wegen JavaScript, (Pre-)Rendering oder die UI dazu anzeigen willst (zB in WPF) etc..
Vermutlich brauchst Du zweiteres, weil Du mit dem DOM arbeitest in Deinem Code.
In beiden Fällen musst Du "einfach" async await korrekt anwenden, wie in meinem Beispiel.
string html = await InternetAsync(LStr_Link, WvLinkInhalt);
async await ist wirklich was, was Du verstehen musst. Lern es. Inverstier 20 Stunden. Du brauchst es jeden Tag. Da reicht es nicht einfach den Code zu kopieren.
Das ist wirklich mittlerweile ein Basiswissen in C#, das man wirklich leider nicht mit Copy Paste lernen kann.
Und wenn Du etwas "nicht hin kriegst", was kriegst Du nicht hin? Erklär es konkret, dann kann man auch konkret antworten. Aber mein Ziel ist es, dass Du es verstehst und dann werde ich nicht Dein Code Generator sein. Da hast nix gelernt und Dir is nich geholfen.
Es gibt keine Garantie, dass Drittanwendungen sich so verhalten, wie Du Dir das wünscht.
bei z.B. Bilder aus Chrome oder Edge bekomme ich nur FileNames und MemoryStream gibt null aus.
Verwendet man Drag and Drop mit Chromium-basierten Browsern (zB das Bild einer Webseite), dann wird standardmäßig die URL in der aktuellen Outlook-Version rein kopiert und nicht die Datei selbst.
In alten Versionen wird das Drag- and Drop fast vollständig blockiert.