@micha7 sagte in Soundplayer verschluckt den Anfang eines Sounds:
Eine Frage habe ich noch. Im Kopf der *.wav Datei muss ja drinstehen wie lang die Datei ist. Wie würde man das machen, wenn die Länge des Sounds am Anfang noch gar nicht bekannt ist? Beim Synthesizer besteht der Sound aus drei Teilen: Der Anfang mit steilem Anstieg und Abfall auf ein niedrigeres Nieveau, dann der Mittelteil mit variabler Länge (solange die Taste gedrückt gehalten wird), und dann der Schluss mit einem Abfall bis auf Null. Ist euch dazu ein Programmier-Beispiel bekannt?
Das kannst du so sowieso nicht so machen, also nicht mit einem MemoryStream in den du schreibst. Weil in den MemoryStream schreiben während der gespielt wird... das wird vermutlich nix.
Wenn du "live" Sound ausgeben willst, dann musst du den auch "live" abspielen. D.h. du musst die Audio-Daten in kleinen Stücken berechnen und dann Stückchenweise an das Audio-Device schicken. Dabei immer schauen dass nicht zu viel gepuffert ist (weil das Delay sonst zu gross wird), und natürlich darf auch nicht zu wenig gepuffert sein, weil es sonst Aussetzer gibt.
Je nach API läuft das dann etwas unterschiedlich: Variante 1) ist genau so wie beschrieben, da gibt es einen Aufruf mit dem du einfach ein weiteres Stück Audiodaten an das Device übergibst.
Variante 2) ist ein Ring-Puffer. Dort definierst zuerst einen Ring-Puffer mit einer bestimmten Länge, sagen wir 200ms. Den kannst du dann "starten", d.h. das Audio-Device fängt an die Daten in dem Puffer als Loop abzuspielen. Und während das Audio-Device den Puffer immer und immer wieder spielt, kannst du ändern was drinnen steht. Das ganze muss natürlich mit dem Abspielvorgang synchronisiert werden. Nicht ganz einfach zu erklären, aber es gibt dazu einige Beispiele im Netz zu finden.
Ist aber alles wesentlich aufwendiger als mal schnell einen System.Media.SoundPlayer zu erzeugen.
Vielleicht gibt es aber auch schon brauchbare .NET Libraries die das irgendwie abstrahieren, so dass du nur noch die Funktion schreiben musst die die neuen Audiodaten liefert. Wobei da .NET durch die nicht-deterministischen Pausen durch den GC nicht wirklich gut geeignet ist. Sowas macht man eher mit C oder C++.
Warum ist das kein deutscher Satz?
Es hat gestern regnen.
Weil es in der Sprache nicht vorgesehen ist.
Wenn du sowas machen möchtest, hole deine IF Bedingung aus dem Switch block raus und mache 2 Switch Statements
Also
if(true){
switch(a){
...
}
}else{
switch(a){
...
}
}
Grüße
Eine vermutlich nicht sehr elegante aber funktionierende Variante ist einfach die PATH Environment-Variable zu ändern. Natürlich nur für den eigenen Prozess. Siehe https://docs.microsoft.com/en-us/dotnet/api/system.environment.setenvironmentvariable?view=netframework-4.8
Oder, wenn du willst dass die DLLs gar nicht als Files irgendwo rumliegen müssen, dann google mal nach .net embedded assemblies. Wobei es da Fallstricke gibt, mit manchen Third-Party Assemblies geht das nur begrenzt. Für eigene Assemblies verwende ich das allerdings erfolgreich und bisher ohne Probleme. Und zwar die Variante über den AppDomain.AssemblyResolve Event. Ein Hinweis dazu allerdings: wenn das .NET Framework die Assembly selbst findet, wird AppDomain.AssemblyResolve nicht aufgerufen. D.h. wenn man eine "falsche" Assembly neben die .exe legt (z.B. alte, verbuggte Version), dann wird eben die alte verbuggte Assembly geladen.
@Swordfish Das schließe ich natürlich nicht aus, wäre aber trotzdem etwas verwunderlich, da die restlichen benötigten Kommandos ohne Probleme funktionieren.
Egal, kommen wir zum Eingangsthema zurück.
@uhomm
Da du ja selbst schon schreibst, dass die Klassen unabhängig von der GUI sein sollen würde ich davon, wie andere vor mich auch schon, abraten die Grafiken mit in die Klasse aufzunehmen.
Das wäre dann übergeordnete Logik, wie die Darstellung zu erfolgen hat und hat dann in der Klasse nichts zu suchen.
Kann es sein, dass du manche Explorer-Fenster als Administrator geöffnet hast und dein Programm deshalb keinen Zugriff darauf hat? Hast du schonmal dein Programm als Administrator ausgeführt und geschaut was dann passiert?
MfG SideWinder
@Quiche-Lorraine
SendMessage geht nur dann über die Message-Queue, wenn das Fenster einem anderen Thread gehört. Ansonsten wird die WindowProc direct aufgerufen. Weil das ja sonst auch nie gehen könnte.
Wenn du natürlich eine Parent/Child Beziehung zwischen Fenstern hast die unterschiedlichen Threads gehören, dann erklärt das so ziemlich alles an Problemen was du mit Deadlocks/Hangs nur haben kannst. Das ist fummelig^10 und deswegen lässt man es auch bleiben.
Ich habe da nämlich so den Verdacht dass das CreateWindow Nachrichten an das Parent Fenster schickt.
Ja, klar. Aber was CreateWindow macht oder nicht macht is ja erstmal egal, wenn sogar ein einfaches SendMessage blockt.
Dadurch kommt die Message Pump der Visualisierung aber nicht mehr an die Nachrichten des Hauptfensters heran (siehe MSDN) und, so vermute ich, kommt es zu Problemen beim setzen der Parent-Child Beziehung.
Falls du damit meinst du versuchst Nachrichten für Fenster X welches von Thread T1 erstellt wurde aus einem anderen Thread T2 zu pumpen: korrekt, das geht nicht.
Hallo Leute,
ich möchte gerne eine .net-standard-lib dotfuscaten. Da ich VS2019 verwende, dachte ich an den PreEmptive Dosfuscator. und frage ob das ne gute Entscheidung ist, oder einen anderen nehmen soll und dann welchen?
Zudem frage ich mich wieso eine build in Dotfuscation in VS vorhanden ist? und der code schon beim compilieren verschlüsselt wird!? So wie ich gelesen hab, wird ja bei den dotfuscation tools die fertige dll verschlüsselt richtig?
Was muss ich generell beachten, wenn ich dll herausgebe, damit diese nicht so einfach lesbar decompiliert werden können!?
Habt ihr da ein Tipp bzw. Vorgehensweise?;)
Danke und schönen Sonntag noch;)
@micha7 sagte in Viele Zahlen in ein Array schreiben:
stimmt, diese Lösung ist noch besser.
Aber sie ist nicht identisch und tut vor allem nicht das, was du ursprünglich gefragt hast. Denn falls du irgendwo b kopiert hast, änderst du dort die Daten nicht und hast dann 2 unterschiedliche Arrays. Du schreibst also nicht in das Array hinein, sondern nimmst einfach ein neues, anderes Array. Es ist also etwas anderes - ob es das ist, was du willst, musst du anhand deines restlichen Codes entscheiden.
Mit Linq in einer Zeile machbar: https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable.max
Wahrscheinlich nicht die Idee deiner Aufgabenstellung, aber die vier Zeilen solltest du noch alleine schaffen. Ansonsten zeig was du probiert hast und/oder stelle Fragen wo du Verständnisschwierigkeiten hast.
@Mechanics sagte in Sortier-Reihenfolge im DataGridView:
DataGridView.ColumnHeaderMouseClick
Damit geht es sogar noch besser, nämlich nur wenn man in die Kopfzeile klickt.
Michael
Guten Morgen Leute,
ich habe schon bissel recherchiert umd "ConfigureAwait(false)" der TPL zu verstehen. Wenn ein Task mit ConfigureAwait(false) markiert versehen wird, dann kommt dieser in einem "anderen" Thread Context zurück.. was ich gar nicht verstehen was damit gemeint ist
Aber zuerst, habe ich den überhaupt Async/Await verstanden? Nehmen wir an ich habe 3 Aufgaben seriell zu erledigen, und jede Aufgabe gibt ein Ergebnis für die nächste zurück. Dann würde ich das ganze so mit der TPL machen:
async void DoCompleteWorkAsync()
{
object data = ...;
object myResult = null;
var resA = await DoWorkAAsync(data);
var resB = await DoWorkBAsync(resA);
var resC = await DoWorkCAsync(resB);
myResult = resC;
}
Das ist schonmal klar (denk ich). Wenn ich das ganze nun mit klassischen Thread (ohne den async/await syntatic sugar), lösen würde, würde das so ausehen : (hier verschachtele ich die Kontexte der Threads)
VAriante A:
void DoCompletWorkA()
{
object data = 0;
object myResult = null;
var waitAll = new AutoResetEvent(false);
ThreadPool.QueueUserWorkItem((i) =>
{
var resA= DoWorkA(i);
ThreadPool.QueueUserWorkItem((i1) =>
{
var resB = DoWorkB(i1);
ThreadPool.QueueUserWorkItem((i2) =>
{
var resC = DoWorkC(i2);
myResult = resC;
waitAll.Set();
}, resB);
}, resA);
}, data);
waitAll.WaitOne();
}
und nun Variante B (welche dann async/await mit ConfigureAwait gleicht.. richtig??) :
void DoCompletWorkB()
{
object data = 0;
object myResult = null;
var waitAll = new AutoResetEvent(false);
object resA = null;
ThreadPool.QueueUserWorkItem((i) =>
{
resA = DoWorkA(i);
waitAll.Set();
}, data);
waitAll.WaitOne();
object resB = null;
ThreadPool.QueueUserWorkItem((i1) =>
{
resB = DoWorkB(i1);
waitAll.Set();
}, resA);
waitAll.WaitOne();
object resC = null;
ThreadPool.QueueUserWorkItem((i2) =>
{
resC = DoWorkC(i2);
waitAll.Set();
}, resB);
waitAll.WaitOne();
myResult = resC;
}
hier springe ich immer wieder nach jeder Arbeit in den ursprungs Kontext zurück.. ist nun das was ConfigureAwait(false) tut?
Oder habe ich generell was nicht kapiert?;)
Eine generelle Liste aller Operatoren gibt es in C#-Operatoren (welche [fast] alle von den Standard-Datentypen unterstützt werden).
Eine einzelne Auflistung gibt es auch noch unter Ausdrücke: Arithmetische operatoren (und folgende Abschnitte).
Und noch ne Frage zu folgenden Code:
ich will eine list von async events ausführen, das anfügen und löschen von IAsyncEventHandler kann asynchron passieren, deswegen mach ich eine kopie via lock.. kann ich das auch elliganter lösen?
public async Task AsyncInvoke(Args input, CancellationToken cancellationToken)
{
/* need to sync _requestHandler access */
IAsyncEventHandler[] Aggregate()
{
lock (_requestHandler)
{
return _requestHandler.ToArray();
}
}
await Task.WhenAll(Aggregate());
}
EDIT: So ists wohl elegante;:
await _semaphoreSlim.WaitAsync(cancellationToken);
try
{
await Task.WhenAll(_requestHandler);
}
finally
{
_semaphoreSlim.Release();
}
}
wobei ich gelessen habe das dies zweck Threading context mit ConfigureAwait probleme machen kann?