Laden...

Forenbeiträge von PoWl Ingesamt 219 Beiträge

07.02.2018 - 18:18 Uhr

Alles klar. Danke für die Antworten!

Ich denke ich werde mich dann mal mit SQlite beschäftigen, das scheint genau das zu sein, was ich brauche 🙂

Eine eigene API möchte ich nicht schreiben, das Tool selbst wird schon genug Arbeitsaufwand mit sich bringen, da muss das Drum-Rum einfach sitzen sonst steh ich am Ende ganz ohne Ergebnis da, man kennt das. 😁

07.02.2018 - 13:27 Uhr

Ich fürchte, dass Performance hier nicht Dein ausschlaggebendes Kriterium sein wird.
Eine Serialisierung zB. von Json in Dateien wird erst bei einer dreistelligen MB-Größe in Sachen Performance bei solchen Anwendungen/kleinen Tools relevant.

Dass ich das wahrscheinlich nicht mal merke wenn ich da mal meine 1MB Daten kurz auf meine SSD schreibe habe ich mir schon gedacht. Aber das passiert dann halt quasi jedes mal, wenn ich auch nur irgend eine Aktion mit einem Musik-Titel ausführe, und wenn es nur ist, z.B. eine Checkbox anzuklicken um den Titel irgendwie für irgendetwas zu markieren. Das erscheint mir doch irgendwie amateurhaft. Also dann wohl eher Datenbank.

Access eignet sich dafür nie. NIE NIE NIE NIE. NICHTS spricht für Access. NICHTS.
Ja, SQlite schon eher.

Aber ist MS Access nicht genau für solche Zwecke da? Eine relationale Datenbank in Form einer einzigen Datei lokal auf dem Rechner vorzuhalten und darüberhinaus in Form der Software "Microsoft Access" noch ein komfortables Userinterface zur Verwaltung dieser Datenbank bereitzustellen? Oder muss hierfür Access immer auch auf dem Rechner installiert sein und mein Programm ist hier auf externe Programm-Logik angeweisen?

SQlite ist ja dann quasi das gleiche. Hier halte ich natürlich auf jeden Fall die ganze SQlite-Logik in meiner Software vor und kann mit externen Tools meine Datenbankdatei laden und anschauen.

Gibt es sonst noch etwas zu beachten?

Wenn du ganz sicher gehen willst, dass deine DB nicht durch einen Schreibvorgang bei einem Stromausfall beschädigt wird, kannst du auch regelmäig Backups durch einfaches Kopieren der DB anfertigen.

Guter Punkt. Das würde in jedem Fall helfen.

07.02.2018 - 13:10 Uhr

Hi,

ich würde gerne eine Playlistverwaltung in C# schreiben, welcher über eine API mit einem Musikstreamingdienst in Verbindung steht und dort z.B. automatisch neue Releases von Künstlern in spezifische lokal im Programm gespeicherte Playlists einsortiert.

Diese Playlists muss ich nun natürlich in Form von Tabellen in meiner Software abbilden. Im einfachsten Fall würde ich hier einfach Klassen und Listen verwenden. Jedoch muss ich sicherstellen, dass nicht nur nach Beendigung der Software der aktuelle Programmzustand lokal auf dem Rechner zwischengespeichert wird sondern auch zwischendurch immer mal wieder, falls es zum Absturz der Software oder des Computers kommt, ohne dass zuvor gespeichert wurde.

Je nach Nutzungsgrad der Software stelle ich es mir nicht gerade performant vor, nach jedem Arbeitsschritt die gesamten Datenobjekte zu serialisieren und in eine Datei reinzuspeichern. Abgesehen davon, was wohl passiert, wenn während des Schreibvorgangs der PC mal abstürzt und damit die Datei hinüber ist. D.h. ich möchte also dass der aktuelle Programmzustand permanent live mit einer Art Datenbank synchronisiert wird so dass ich nach einem Softwareabsturz einfach alles wieder laden kann und genau da weitermachen kann, wo ich zuvor aufgehört hatte. Idealerweise würde hierbei die Synchronisation mit meinen Datenobjekten völlig automatisch funktionieren oder ich würde innerhalb meines Programms einfach direkt mit der Datenbank kommunizieren (ohne dass alle Daten in Form von Objekten permanent im RAM vorgehalten werden)

Welche Technik/Strategie eigent sich hierfür? Auf eine getrennt zu installierenden Datenbankserver bzw. generell Zusatzsoftware würde ich gerne verzichten. Empfiehlt sich vielleicht sogar eine Access-Datenbank? Oder so etwas wie SQlite? Bei der Fülle an Möglichkeiten fehlt mir irgendwie der Überblick 🤔 Wünschenswert wäre am Ende auch ein Format, das es zulässt, die Daten hinterher noch mit externer Software darstellen/bearbeiten zu können, was z.B. für XML oder eine Access-Datenbank sprechen würde.

lg Paul

01.09.2017 - 16:38 Uhr

Hi,

der ursprungs-thread ist ja nun schon etwas alt, aber das Thema interessiert mich auch, da ich ein kleines recording-tool für den Stereomix coden möchte, für das es sinnvoll wär, temporär alle stör-Sounds deaktivieren zu können.

Hat jemand eine Idee, wonach ich da suchen kann, um auf eine Lösung zu kommen?

lg

12.05.2017 - 07:18 Uhr

Hi,

ich habe hier ein kleines Windows Tablet, welches ich gerne als Fernsteuerung für diverse Bastelanwendungen verwenden würde, z.B. Lichtsteuerung. Da läuft dann ein selbstgeschriebenes Fullscreen-GUI Programm, welches ich z.B. in WPF/C# schreibe, welches dann über Bluetooth oder WLAN mit der Hardware kommuniziert. Damit das Programm jederzeit reagieren kann darf das Tablet währenddessen nicht in einen Energiesparmodus gehen, daher habe ich den Connected Standby (Instantgo) deaktiviert und Windows so konfiguriert, dass es beim Drücken des Ein/Aus-Schalters lediglich der Bildschirm ausgeschaltet wird. Das funktioniert auch so weit.

Allerdings ist der Touchscreen des Tablets weiterhin aktiv und jede Berührung führt dazu, dass der Bildschirm, wie bei einer Mausbewegung, automatisch wieder an geht.

Wie kann ich das verhindern? Ich muss quasi den Touchscreen deaktivieren, sobald der Bildschirm ausgeschaltet wird und ihn wieder aktivieren, sobald der Bildschirm angeschaltet wird.

Geht das irgendwie durch eine Einstellung im Betriebsystem oder muss ich hier quasi ein kleines Tool im Hintergrund laufen lassen, welches den Betriebszustand des Bildschirms überwacht und den Touchscreen passend ein- und ausschaltet? (Wie auch immer man das realisieren kann)

Eine Möglichkeit, den Touchscreen zu deaktivieren bestünde z.B. darin, das zugehörige Gerät zu deaktivieren. Das wiederum ginge wohl ganz einfach mit dem Commandline-tool devcon.exe (Windows Device Console), was mir aber als eine nicht allzu überaus elegante Methode erscheint.

lg Paul

22.12.2016 - 14:40 Uhr

Gut, das wiederum macht Sinn. Es ist ja auch nicht zwangsläufig immer vorgesehen, dass ein Programm unendlich lange geöffnet bleibt und immer neue Bilder läd.

Es waren übrigens nur 44 unterschiedliche Bilddateien, da passen die 255 Objekte nicht dazu.

22.12.2016 - 12:44 Uhr

Wenn ich das richtig verstanden habe, wird bei deaktiviertem Cache & URI der Stream offen gelassen.
Bei Aktivierten Cache wird die Datei in den Arbeitsspeicher geladen & der Stream wieder geschlossen, hierbei gibt es die Optionen 'OnDemand & OnLoad' deren namen für sich selbst sprechen.

Hm, aber was für einen Sinn ergibt das? Immerhin kann man von außen gar nicht auf den Stream zugreifen, um ihn zu schließen. Zudem scheint die Anzahl der verwaisten Objekte nicht mit der Anzahl der bisher angezeigten Bilder übereinzustimmen. Im Screenshot des Profilers mit dem Leak verwaisen innerhalb von ca. 2332 Sekunden 225 Uri-Objekte und 253 WeakReference-Objekte. Jedoch wurden in dieser Zeit auch 777 Bilder angezeigt. Im Beispielcode von MSDN wird es ja auch so gemacht, dass dem BitmapImage einfach nur eine UriSource zugeteilt wird. Ob die MSDN-Ersteller wirklich ein Leak in Kauf nehmen?

Woher hast du die Info, dass der Stream offen gelassen wird? Im Code geguckt? Das schaue ich mir auch mal an.

22.12.2016 - 11:48 Uhr

Ich habe es bisher gar nicht rausgenommen 😁 Derzeit entwickle ich die Software ja noch und ich finde es durchaus interessant, zu beobachten, ob oder wann der Fehler wieder auftritt bzw. möchte ja auch meine Statusausgaben auf dem Zielsystem sehen. Später, wenn die Anwendung dann einfach nur noch laufen soll, werde ich die Konsole abschalten.

22.12.2016 - 11:40 Uhr

Ah! Ja das dachte ich mir schon, dass die Auslagerungsdatei schon während des Betriebs genutzt wird. Gemäß diesem elegant designten Einstelldiaglogfenster hier ist die jedoch auf 1792MB Größe begrenzt. Das ist mehr, als auf der Festplatte ohnehin noch frei ist, das sollte ausreichen. Der Physische Arbeitsspeicher ist laut Ressourcenmanager soweit belegt, dass noch dauerhaft 200MB frei sind.

Ich habe den Fesplattenspeicher auch mal auf 20MB reduziert, um den Fehler weiterhin zu provozieren. Bisher ist der leider nicht einmal mehr aufgetreten.

22.12.2016 - 11:08 Uhr

Also wenn man einfach die Fehlermeldung googelt, dann ist fast überall davon zu lesen, dass die Auslagerungsdatei vollläuft bzw. die Größe eben dieser angepasst werden sollte.

>

Verständlicherweise hast du nicht den ganzen Thread gelesen aber: Das kann praktisch nicht die Ursache gewesen sein. Zum Zeitpunkt des Vorfalls war noch mehr als 1Gb Festplattenspeicher übrig und der RAM nur zu 60% ausgelastet.

War wohl ein Bug 🤔

21.12.2016 - 20:44 Uhr

Das Leak ist in meinen Augen immer noch das gewesen, dass Du die Streams nie geschlossen hattest.
Da Du nun die Uri verwendest, öffnest Du keinen Stream mehr, den Du selbst schließen musst.
=> behoben.

Moment mal 😁 Es war genau andersrum. Ich verwendete am Anfang die Uri und diese hatte ein Leak. Später habe ich die Variante mit dem Stream übernommen (der per using auch geschlossen wurde), diese Variante hatte kein Leak. Eine Variante, in der ein Stream erzeugt, aber nie geschlossen wurde, gab es nie. Deshalb wundere ich mich ja so, warum die Uri-Variante denn ein Leak erzeugt, sollte sie doch seitens .Net so beschaffen sein, dass sie das nicht tut, da der Programmierer bei deren Verwendung die Verantwortung über das ordnungsgemäße Schließen der Ressourcen an diese komplett abgibt.

In der Tat scheint übrigens Dein Console.Writeline für die Exception verantwortlich zu sein; das System.IO.__ConsoleStream.Write ist mir im StackTrace irgendwie nicht aufgefallen.

Das ist ja echt abgefahren. 🤔

21.12.2016 - 20:32 Uhr

Aber klar 🙂 Was das bewirkt kann man ja hier nachlesen:
BitmapCacheOption-Enumeration

Jedoch kann ich mir keinen Reim darauf machen, warum das Caching dafür verantwortlich sein soll, dass ein Memory-Leak entsteht.

v.a. weil "Caches the entire image into memory. This is the default value." die Default-Einstellung ist. Was spricht dagegen, das Bild im Arbeitsspeicher zu cachen? Warum sammeln sich Uri-Objekte an, obwohl diese schon längst nicht mehr benötigt werden? Das lässt die Dokumentation offen.

21.12.2016 - 14:08 Uhr

Ja richtig, aber auch in der Doku (https://msdn.microsoft.com/de-de/library/system.windows.media.imaging.bitmapimage%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396)

wird es wie folgt gemacht:

// Create the image element.
Image simpleImage = new Image();    
simpleImage.Width = 200;
simpleImage.Margin = new Thickness(5);

// Create source.
BitmapImage bi = new BitmapImage();
// BitmapImage.UriSource must be in a BeginInit/EndInit block.
bi.BeginInit();
bi.UriSource = new Uri(@"/sampleImages/cherries_larger.jpg",UriKind.RelativeOrAbsolute);
bi.EndInit();
// Set the image source.
simpleImage.Source = bi;

Das ist genau der Code, welcher bei mir zu einem Leak führt. 🤔

21.12.2016 - 13:23 Uhr

MrSparkle, daher habe ich die Bilder extra auf meinen privaten Webspace geladen, wo ich sichergehen kann, dass sie auch in 10 Jahren noch online sind 😉 Aber ich verstehe.

Hier noch der Screenshot der alten Methode:

21.12.2016 - 12:21 Uhr

Die Konsolenausgabe nutze ich, um Statusausgaben zu machen, die ich während der Entwicklung meines Programms nutze, um dessen Verhalten zu beobachten. Richtig brauchen tu ich sie nicht.

Ich habe mich nun mal ans profiling gemacht und erst mal den internen Profiler von Visual Studio genutzt (warum auch nicht 😄).

Alte Methode


var bitmap = new BitmapImage(new Uri(System.IO.Path.Combine(mediaDir, imageFiles[currentImageFile])));
imageElements[currentImageElement].Source = bitmap;

Hier habe ich in der Tat ein Leak feststellen können. Allerdings ein viel kleineres als ich bisher erwartete. Die Anzahl an Objekten steigt permanent. Seltsamerweise nicht in der gleichen Geschwindigkeit, wie ich die Bilder wechsle. Es werden hier auch nicht die gesamten Bilddaten im RAM behalten sondern nur einige kBytes. Das meiste sind Uri und WeakReference.
Kann jemand nachvollziehen, warum .Net das macht? Wie ich ja bereits erörtert habe, ergibt es für mich keinen Sinn, wieso BitmapImage die Möglichkeit bereitstellt, ihm eine UriSource zu übergeben, wenn man sich damit sowieso ein MemoryLeak erzeugt. Ist dieses Verhalten völlig klar und ich habe nur Tomaten auf den Augen oder ist das ein .Net-Bug, den man sogar mal melden sollte?
Sowohl bei den Objekttypen WeakReference als auch bei Uri ist es immer der Eintrag "Hashtable [Statische Variable ImagingCache._imageCache]", bei dem die Verweiszahl kontinuierlich steigt. Was ist das denn? Und warum wird das nicht freigegeben? Nachdem das Image-Steuerelement schon lange ein anderes Bild geladen hat dürfte doch überhaupt keine Referenz mehr auf irgend ein Überbleibsel eines ehemals geladenen Bildes bestehen und der GC müsste das einfach wegräumen. Nach meiner Vorstellung zumindest. Das ganze erstaunt mich auch ein wenig, im negativen Sinne. Habe ich hier einen Sonderfall erwischt oder muss man an jeder Stelle und Ecke in .NET aufpassen und irgendwelche besonderen Codeteile einbauen, damit man sich nicht ein Memory-Leak erzeugt? X(

Neue Methode


var bitmap = new BitmapImage();
using (var stream = File.OpenRead(System.IO.Path.Combine(mediaDir, imageFiles[currentImageFile])))
{
    bitmap.BeginInit();
    bitmap.CacheOption = BitmapCacheOption.OnLoad;
    bitmap.StreamSource = stream;
    bitmap.EndInit();
    bitmap.Freeze();
}

imageElements[currentImageElement].Source = bitmap;

Dieser Code läuft hingegen seit >500 Minuten (über Nacht laufen lassen) völlig rund. Durch das Ersetzen von UriSource mit StreamSource konnte ich die Leaks weitesgehend eindämmen.

Nundenn, ein Leck ist abgedichtet! 🙂 Danke soweit für die Hilfe!
Ob das das ursprüngliche Problem jedoch löst ist ungewiss. Ich werde sehen, ob bzw. wann die Exception wieder auftritt.

20.12.2016 - 21:33 Uhr

@FZelle
Der Medien-Ordner beinhaltet 40 Bilder, alle so ca. 2-3Mb groß. Die Bilddateien dürften in Ordnung sein, jedes einzelne Bild wurde nun schon etliche Male erfolgreich geladen.

@ujr
Das ist ja interessant! Ob das wohl auch systemabhängig ist? Immerhin lasse ich die Software auf schwachbrüstigen Windows-Tablets laufen, die sich sowieso etwas buggy verhalten. Allerdings ist ja hier klar von "Not enough storage is available to process this command". Bei mir ist es "Not enough quota...". Ich beziehe das mal in meine Untersuchung mit ein

@MrSparkle
(Pardon, wie gesagt hatte ich mich da etwas missverständlich ausgedrückt. Nochmals zur Erklärung: Ich als .Net-Neuling bin nur irritiert über den Umstand, dass sich etwaige Leaks, scheinbar überhaupt nicht äußerlich bemerkbar machen, dass ein Memory- oder Handle-Leak nicht in einem kontinuierlichen Anstieg der Gesamtauslastung dieser jenen Ressource führt, die sich im Taskmanager zwar nicht unter dem entsprechenden Prozess, jedoch aber in der Gesamtübersicht bemerkbar machen müsste. Das ist für mich ein Widerspruch. Sofern der Taskmanager überhaupt etwas zu gebrauchen sein soll muss er ja die Zahl dieser im gesamten System verbrauchten Ressourcen irgendwie korrekt anzeigen, was Abt ja auch bestätigt hat. Wenn ich alle 3 Sekunden ein 3Mb-Bild lade und dieses nicht wieder freigegeben würde müsste mein gesamter Arbeitsspeicher innerhalb von 5 Minuten voll sein. Auch müsste die Anzahl im System verwendeter Handles (sofern diese beim Laden eines Bildes nicht freigegeben werden) um 1200 Handles pro Stunde steigen. Auf einem System, welches nur 1Gb RAM und im Schnitt 23000 dauerhaft vergebene Handles hat macht sich ein solcher Anstieg innerhalb kürzester Zeit bemerkbar. Ich konnte wie gesagt nichts davon beobachten. Insofern ist es für mich, mangels besseren Verständnis, eben für mich fraglich, ob hier denn überhaupt ein Leak vorliegt. Gibt es verschiedene Arten von Handles? Nach wie vor ist es verwunderlich, welchen Sinn die Möglichkeit, das BitmapImage per UriSource-Property zu beladen, haben soll, wenn es doch sowieso zu einem Leak führt. (Außer es handelt sich um einen .Net Bug).

Den Code aus dem Link, den du eben genannt hast, habe ich ja bereits (wie oben aufgezeigt) übernommen. Ich lasse mein Programm derzeit damit laufen um zu schauen, ob der Fehler damit immer noch auftritt.

Zum Profiler: Den Tipp habe ich keineswegs ignoriert. Ich bin nur gerade noch dabei, verschiedene Profiler auszuprobieren und versuche diese auf mein Problem anzusetzen. Ich muss erst mal lernen, wie man diese Programme überhaupt benutzt und auf welche Weise sie mir nützliche Informationen liefern. Aus Höflichkeit und da ich der Bittsteller bin, hielt ich es für angemessen, eine geringe Reaktionszeit zu bewahren und im Thread auch zwischendurch etwaige Rückfragen zu beantworten.

Ich klinke mich besser erst mal aus und melde mich zurück, sobald ich das Programm mit einem Profiler untersucht habe. bzw. die Exception erneut auftritt. 🙂

20.12.2016 - 17:16 Uhr

Sehr gerne. Das hier ist der Code der Timer-Tick Routine, so wie er vor ein paar Tagen zum Zeitpunkt des Auftretens des Fehlers aussah:


        async private void ImageChangeTimer_Tick(object sender, EventArgs e)
        {
            Random rnd = new Random();

            lock (locker)
            {
                nextimage:
                do
                {
                    currentImageFile = rnd.Next(0, imageFiles.Count);
                    if ((history.Contains(currentImageFile)))
                        Console.WriteLine("douh! " + currentImageFile);
                }
                while (history.Contains(currentImageFile));
                history.Enqueue(currentImageFile);

                Console.WriteLine(currentImageFile);

                currentImageElement++;
                if (currentImageElement > 1)
                    currentImageElement = 0;

                try
                {
                    // Achtung, das hier wurde mittlerweile durch obengenannten Code geändert!
                    imageElements[currentImageElement].Source = new BitmapImage(new Uri(System.IO.Path.Combine(mediaDir, imageFiles[currentImageFile])));
                }
                catch (FileNotFoundException)
                {
                    log("Error! File not Found: " + imageElements[currentImageElement]);
                    imageFiles.RemoveAt(currentImageElement);
                    history.Clear();
                    goto nextimage;
                }
            }

            await Task.Delay(500); // Animation flüssiger machen

            if (currentImageElement == 1)
                sbFadeIn.Begin(Image2);
            else
                sbFadeOut.Begin(Image2);
        }

Darüberhinaus macht mein Programm nichts. Es ist der einzige Timer der läuft. Andere Programmteile werden nicht aufgerufen. Ich konnte bisher leider den Fehler nicht reproduzieren. Das Programm läuft gerade auf allen 3 Tablets seit 15h durch. Ich lass es mal weiter laufen.

Mittlerweile logge ich auch alle Exceptions mit. Im Internet fand ich, dass AppDomain.CurrentDomain.FirstChanceException += CurrentDomain_FirstChanceException; ausnahmslos alles einfängt, was an Exceptions geworfen wird.

        private void CurrentDomain_FirstChanceException(object sender, System.Runtime.ExceptionServices.FirstChanceExceptionEventArgs e)
        {
            Exception ex = e.Exception;
            log("FirstChanceException: " + ex.ToString());

            while (ex.InnerException != null)
            {
                ex = ex.InnerException;
                log("InnerException: " + ex.ToString());
            }
        }
19.12.2016 - 13:21 Uhr

Und du hast die bilder auch disposed?

Nein, ich weiß leider nicht, wie ich das tun sollte. BitmapImage stellt keine Dispose-Methode bereit. Und das Image-Steuerelement stellt auch nichts bereit, womit das möglich wäre.

19.12.2016 - 12:48 Uhr

Hast du dir im Taskmanager auch schon mal die GDI-Objekte angesehen? Ich weiß nicht, ob WPF überhaupt irgendwie GDI benutzt, aber unter Windows Forms könnte das auch ein möglicher Grund sein.

Also im Taskmanager / Process Monitor werden bei den Handles, GDI-Objekten und Threads über den gesamten Zeitraum eine nahezu konstante Zahl angezeigt. Wie Abt schon gesagt hat kann man sich ja auf diese Angaben leider nicht verlassen 🙁 (Handles: 910, Threads: 28, GDI-Objekte: 41)

Wenns ein speicher Problem ist kann es gut sein das du die WPF Bindings nicht richtig implementiert hast.

Interessant, scheinbar erzeugt man ja an allen Ecken und Stellen in WPF irgendwelche Memory Leaks. Bindings nutze ich aber nicht. Ich habe nur zwei Image-Steuerelemente, die abwechselnd mit neuen Bildern beladen werden und bei dem das vordere Image immer ein- bzw. ausgeblendet wird.

Noch mal eine grundlegende Frage: Müsste sich bei einem Memory-, Handle- oder GDI-Leak nicht eine der Zahlen auch im ungenauen Taskmanager in der Prozess-Ansicht im laufe der Zeit aufblähen? Die verändern sich halt überhaupt nicht. ist der Taskmanager bei .NET-Prozessen nicht nur ein "Schätzeisen" sondern vollkommen komplett nutzlos? Nur damit ich weiß, welches Ausmaß das hat.

18.12.2016 - 18:19 Uhr

Ja, die Anzahl der Handles springen in der Tat im 100er-Bereich hin und her. Müsste sich bei einem Handle-Leak nicht aber insgesamt gesehen eine langfristige Tendenz nach Oben abzeichnen?

18.12.2016 - 16:55 Uhr

Pardon, vielleicht habe ich mich falsch ausgedrückt: Ich habe lediglich das Gefühl, das Ressourcenproblem ist ein Gespenst, da es (bis auf die Exception) keine sichtbaren Anzeichen gibt. Ich wundere mich lediglich. Denk dran, ich bin ein Neuling, man vergebe mir. Einen Profiler bin ich ja auch gerade am suchen, jedoch muss ich mich da auch erst mal einarbeiten. Vielleicht liefert der mir ein paar interessante Eindrücke.

Dein Code hat(te) hier ein Leck und bei dem Aussageinhalt bleibe ich auch.

Du hast deutlich mehr Erfahrung, daher glaube ich dir das nur allzu gerne! Ich kann jedoch lediglich nicht nachvollziehen, warum das denn so ist. Ich umreiße noch mal kurz: Warum entsteht ein Leck, wenn ich das Bild über das Setzten einer UriSource lade (so wie anfangs geschehen), und warum entsteht keines, wenn ich es über die StreamSource lade (und danach den Stream manuell freigebe). Welche Legitimation hat dann die Existenz des UriSource-Properties, wenn dieses zwangsläufig ein Leck erzeugt? Oder meintest du, das fehlende Freeze() war die Ursache für das Leck?

Dass der Taskmanager hier keine Verlässlichen Angaben liefert, das glaube ich dir auch gerne. Aber wo ist der Fehler in meiner Erörterung? Hat .net die Macht, tausende Handles zu reservieren, ohne dass das im Taskmanager irgendwas davon auftaucht? Auch bei der Gesamtzahl der im System vorhandenen Handles nicht? 🤔

Sie beschreibt schließlich die Quota, was alles mögliche sein kann, Speicher, Handles.. Das habe ich ja nun wie gesagt auch bereits herausgefunden 😁 Jetzt kann ich wohl nur noch auf den Profiler setzen, der mir dann hoffentlich aufzeigen wird, wo das Leck ist. Vielleicht hast du eine Empfehlung?

18.12.2016 - 16:32 Uhr

😭

Na gut, back to topic:

not enough quota is available to process this command

Dass das die besagte Fehlermeldung ist, war mir schon von Anfang an klar, obgleich du so freundlich warst, sie irgendwann hier noch mal zu übersetzen. 😉 Dementsprechend konnte ich dazu ja auch ein wenig googeln.

MSDN meint dazu:

Close some applications and try again. If you still get this message, choose System from Control Panel, then choose Virtual Memory and increase the size of your paging file.

Das spricht nun nicht gerade dafür, dass mein Festplattenspeicher begrenzt ist, sondern dass der Arbeitsspeicher ausgeht und man deshalb die Auslagerungsdatei vergrößern soll. Jedoch ist weder mein Festplattenspeicher zu knapp noch habe ich zu wenig Arbeitsspeicher frei. (Laut Task-Manager liegt die Belegung des Arbeitsspeichers bei 70% und die Auslagerungsdatei ist dynamisch. Festplattenspeicher noch >1Gb)

http://stackoverflow.com/questions/12584619/mysterious-not-enough-quota-is-available-to-process-this-command-in-winrt-port
Hier trat die gleiche Fehlermeldung bei jemandem auf, der offenbar zu viele Änderungen im Visual Tree gleichzeitig ausgeführt hat, was auf mich ja nicht zutrifft, aber weiterhin impliziert, dass der Fehler nicht zwangsläufig etwas mit dem freien Festplattenspeicher zu tun haben muss.

Instead, it was about limitations in the Windows messaging system. Apparently it is a little like a stack overflow exception, in that when you make too many changes to the visual tree all at once, [...]

Nach weiterer Recherche ergibt sich: Quotas können alle möglichen Beschränkungen sein.

[...] it sets an upper limit to the counted number of resources of a certain type. Common examples are 10,000 windows, 10,000 GDI objects, 10,000 handles.

Ich werde das ganze nun einfach mal laufen lassen und weiterhin warten, wann und wo die Fehlermeldung das nächste mal auftritt. Dieses mal logge ich auch die InnerExceptions mit.

Zum Ressourcenthema:

Am Anfang sagte MrSparkle:

Um die Freigabe von nicht verwalteten Resourcen wie Bitmaps mußt du dich selbst kümmern, z.B. mit der IDisposible.Dispose-Methode oder mittels using. Das aber funktioniert nicht, da das BitmapImage keine Dispose-Methode zur Verfügung stellt. Da ich keine Möglichkeit dazu habe muss ich davon ausgehen, dass .net sich hier selbst drum kümmert.

Weiterhin sagtest du:

Jede Allokierung eines Bildes nimmt auch ein Handle in Anspruch. Gibst Du dieses nicht frei, dann wird das Handle auch nicht freigegeben. Ich kann jedoch die Anzahl der benutzten Handles nirgendwo ansteigen sehen. Obgleich .net gleich von Anfang an den Prozess mit hunderten Handles startet, von denen möglicherweise ein Großteil gar nichts mit meinem Programm zu tun hat, so müssten die abertausende Handles, die mein Programm nach einiger Zeit in Anspruch nimmt, ja irgendwo sichtbar sein. Ich kann also keinen Leak feststellen, lediglich vermuten. Aber wie gesagt, habe ich darauf ja auch gar keinen Einfluss. Und dabei darf es, wie ich bereits erörtert habe, keine Rolle spielen, ob ich das Bild per Streamreader einlese (und den Stream wieder manuell freigebe) oder ob ich dem BitmapImage-Objekt einfach eine Uri übergebe, und es die Arbeit selbst machen lasse. Darauf muss ich mich ja verlassen können, sonst ergäbe das UriSource-Property überhaupt keinen Sinn, wenn es ein Ressourcenleak erzeugen würde.

Dein Link führt indirekt übrigens zu folgendem weiterführendem Thema:
http://stackoverflow.com/questions/11202807/garbage-collection-fails-to-reclaim-bitmapimage

There was a bug in Wpf that we were bitten by where BitmapImage objects are not released unless you freeze them.
>
was the original page where we discovered the issue. It should have been fixed in Wpf 3.5 sp1 but we were still seeing it in some situations. Try changing your code like this to see if that is the problem:

WPF 3.5 ist jedoch Schnee von Gestern. Nun behauptet der gute Mensch da, das Problem tritt immer noch, also empfiehlt es sich, weiterhin Freeze() zu nutzen. Jedoch ging es dort die ganze Zeit um Memory Leaks. Nicht um Handles oder sonstiges. Und ich kann wie gesagt kein Memory Leak beobachten. Der Prozess bläht sich nicht auf, die RAM-Auslastung des gesamten Systems bleibt konstant.

Edit: Missverständliche Passage entfernt.

18.12.2016 - 15:41 Uhr

Na dann schaue ich mir mal so einen Profiler an.

Ich verstehe jedoch nicht: Wenn mein Programm ein Handle-Leak haben soll. Warum steigt dann die gesamte Anzahl an Handles im System nicht irgendwann deutlich an? Weder die Prozess-Handles noch die im gesamten System verwendeten Handles verändern sich über einen größeren Zeitraum signifikant. Der Prozess belegt laut Task-Manager immer nur um die 912 Handles. Angenommen es werden im Laufe der Stunden hunderte Handles belegt aber nie freigegeben, müsste sich das doch irgendwo bemerkbar machen, auch ohne Profiler? 🤔 Wenn ich alle 3 Sekunden ein neues Bild lade müssten das ja 28800 Handles am Tag sein. Das ist mehr als mein System insgesamt gerade anzeigt, das würde schnell auffallen.

18.12.2016 - 15:20 Uhr

Das ist ja interessant, ich wusste gar nicht, dass man so ohne weiteres auf den Quellcode Zugriff hat. Wir kommen hier aber ein wenig vom Thema ab. An keiner Stelle meines Programms habe ich jemals einen Stream erzeugt, ohne diesen wieder freizugeben.

Dein BitmapImage ist zwar managed, aber will eben die StreamSource haben. Ok. jetzt gibt es ja wie gesagt auch die Möglichkeit, dem BitmapImage keine StreamSource sondern eine UriSource (im Konstruktor) zu übergeben, so wie ich das anfangs gemacht habe. Damit müsste sich ja das BitmapImage darum kümmern, sich die Daten aus der Datei zu holen und die entsprechenden Ressourcen wieder freizugeben. Das folgt allein schon als logischer Schluss aus der Tatsache, dass ich überhaupt keine Möglichkeit habe, mich von Außen darum zu kümmern, also wird BitmapImage an dieser Stelle selber die "Drecksarbeit" machen.

Ich sehe in der BitmapImage-Klasse folgendes:


        public BitmapImage(Uri uriSource) : this(uriSource, null)
        {
           
        }

       public BitmapImage(Uri uriSource, RequestCachePolicy uriCachePolicy) : base(true)
        {
            if (uriSource == null)
            {
                throw new ArgumentNullException("uriSource");
            }
 
            BeginInit();
            UriSource = uriSource;
            UriCachePolicy = uriCachePolicy;
            EndInit();
        }

d.h. der Einzeiler (der Code, den ich anfangs verwendete, mit dem die Exception irgendwann auftrat)

var bitmap = new BitmapImage(new Uri(System.IO.Path.Combine(mediaDir, imageFiles[currentImageFile])));

und

var bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.UriSource = new Uri(System.IO.Path.Combine(mediaDir, imageFiles[currentImageFile]));
bitmap.EndInit();

sind völlig äquivalent.

Unter Windows 10 habe ich im Taskmanager leider nicht mehr die Option, mir die von einem Prozess verwendeten Handles anzuschauen. Wohl aber unter Windows 7. Und dort bleibt die Anzahl an Handles die ganze Zeit über im Mittel konstant. Egal in welcher Art und Weise ich das BitmapImage erzeuge und egal ob ich Freeze() einsetze oder nicht. 🤔 Ich habe mein Programm eben extra mal so modifiziert, damit ich alle bisher vorgestellten Codevarianten per Checkbox einzeln aktivieren und deaktivieren kann. Mit keiner Variante geraten die Handles oder der RAM außer Kontrolle. Selbst mit dem Einzeiler nicht.

18.12.2016 - 14:23 Uhr

Ja danke =), den Link kannte ich bereits deswegen war ich so schnell. Du meinstest wohl auch StackOverflow und nicht MSDN?

Die Freeze-Methode habe ich mittlerweile (ohne dies bereits erwähnt zu haben) auch implementiert. Allerdings würde ich wirklich gerne mal nachprüfen, ob ich irgendwelche Ressourcenleaks habe oder nicht. Ich möchte ja nicht nur aus Angst alle möglichen Codeteile einbauen, ohne dass diese tatsächlich notwendig wären. Ich möchte verstehen, was ich da tue. Ich weiß nur, dass es alle paar Tage mal eine Exception beim laden des Bildes gibt.

Mittlerweile sieht das ganze nun so aus:

var bitmap = new BitmapImage();
using (var stream = File.OpenRead(System.IO.Path.Combine(mediaDir, imageFiles[currentImageFile])))
{
    bitmap.BeginInit();
    bitmap.CacheOption = BitmapCacheOption.OnLoad;
    bitmap.StreamSource = stream;
    bitmap.EndInit();
    bitmap.Freeze();
    stream.Close();
}

imageElements[currentImageElement].Source = bitmap;

  1. bitmap.CacheOption = BitmapCacheOption.OnLoad;
    Was bewirkt das? "Caches the entire image into memory at load time. All requests for image data are filled from the memory store.", das Bild wird also aus der Bilddatei geladen und im Arbeitsspeicher gecached. Aber wird es das nicht sowieso? Bei BitmapCacheOption.Default steht "Caches the entire image into memory. This is the default value.". Wo ist der unterschied?

  2. Muss ich unbedingt einen FileStream verwenden, welchen ich hinterher mit Dispose() wieder vernichten kann, um das Bild zu laden? Ich könnte das Bild auch per bitmap.UriSource laden. So wie ich das verstehe hilft das nur, um die Datei gleich wieder freizugeben aber erzeugt keinen Leak. Oder irre ich mich?

  3. Bbitmap.Freeze()
    Ich habe schon mehrfach gelesen, dass es Memory Leaks gibt, sobald ich das BitmapImage, welches ich dem Image zuweise, nicht freeze. Aber ich kann auch nach Stunden an Laufzeit kein MemoryLeak feststellen. Bisher habe ich gelesen, dass Freeze() das von Freezable abgeleitete BitmapImage so tagged, dass es nicht mehr verändert werden kann. D.h. WPF muss es nicht kopieren, um es anzuzeigen, sondern kann es direkt aus dem Speicher verwenden. Aber wenn es nicht freezed wäre, und WPF es kopieren würde, warum sollte das dann zu irgendwelchen Leaks führen?

Ich verstehe die Zusammenhänge nicht.

Warum genau werden die von BitmapImage verwendeten Ressourcen nicht mehr freigegeben? Das sind doch alles managed Objekte? Warum gibt es kein Dispose()?

18.12.2016 - 13:48 Uhr

Hm ok! 😃
Kann ich mir die verwendeten Handles irgendwo angucken? Die müssten ja dann im Laufe der Zeit kontinuierlich steigen.

Ist der Codefetzen, so wie ich ihn nun gezeigt habe, ausreichend?

Wie gesagt, das BitmapImage stellt kein Dispose() bereit. Ich weiß nun nicht, wie ich mich darum kümmern kann.

18.12.2016 - 12:13 Uhr

Warum stellt ein Bitmap eine nicht-verwaltete Ressource dar? BitmapImage stellt keine Dispose() Methode bereit.

Ich habe zwar folgenden Codefetzen entdeckt:

                    var bitmap = new BitmapImage();
                    var stream = File.OpenRead(System.IO.Path.Combine(mediaDir, imageFiles[currentImageFile]));
                    bitmap.BeginInit();
                    bitmap.CacheOption = BitmapCacheOption.OnLoad;
                    bitmap.StreamSource = stream;
                    bitmap.EndInit();
                    stream.Close();
                    stream.Dispose();

Aber der ändert ja nichts daran, dass das BitmapImage-Objekt im Speicher bleibt. Ich sehe aber auch nach wie vor keine Notwendigkeit, mich darum explizit zu kümmern, denn ich habe ja kein Memory-Leak. Die meisten Bilddateien, welche ich zuvor im Programm geladen hatte, kann ich auch während das Programm noch läuft, im Windows Explorer löschen. D.h. die sind nicht durch mein Programm blockiert.

17.12.2016 - 21:46 Uhr

Hm sehr gerne, aber der Garbage-Collector kommt damit scheinbar ganz gut zurecht. Immerhin bläht sich meine Anwendung ja über die Stunden, die sie läuft, nicht immer weiter auf. Das ist natürlich nicht besonders edel aber es schien bisher auch nicht weiter zu stören. Aber was ist, wenn ich das BitmapImage-Objekt, nachdem ich es dem Image-Steuerelement als Source zugewiesen habe, direkt wieder zerstöre? Verschwindet dann das Image? oder kann ich das einfach so tun?

17.12.2016 - 21:02 Uhr

Danke. Nun sind meine 3 Tablets, auf denen die Software gerade läuft, ja ganz normale Consumer-Geräte mit frisch installiertem Windows 10 Home und haben alle drei noch mehrere 100mb Festplattenspeicher übrig 🤔

Dein StackTrace passt nicht zu Deiner analysierten Code-Stelle. Im StackTrace ist ein eindeutiges Schreiben eines Streams zu sehen zusammen mit einem "maybeFullpath".
Spricht also für die Quota-Situation, also dass Dir irgendwo der verfügbare Festplattenspeicher ausgeht.

Hm ja das sehe ich. Ich dachte nur, dass
"bei P_Slideshow_Vorabversion.MainWindow.<ImageChangeTimer_Tick>d__24.MoveNext()"
impliziert, dass es im Timer-Tick Event auftritt? Ist das nicht so?

Darüberhinaus gibt es in meinem gesamten Code auch keine Stelle, an der einfach so ein Schreibzugriff erfolgt. Und meine Logging-Funktion wird erst dann aufgerufen, nachdem die Exception schon geworfen wurde, um diese zu loggen, was ja auch funktioniert.

Die InnerException habe ich noch nicht untersucht. Ich muss jetzt erst mal abwarten, bis der Fehler wieder auftritt.

16.12.2016 - 19:23 Uhr

Ich habe hier eine WPF Slideshow, die im 3-Sekunden Takt einem von zwei Image-Steuerelementen eine BitmapImage als Source zuweist, welches aus Bildern, die auf der Festplatte liegen, erzeugt wird. Das Programm läuft zwar auf einem hardwareschwachen Tablet, läuft aber über Stunden hinweg problemlos durch. Ca. einmal am Tag passiert es jedoch, dass das Programm einfach abstürzt. Ich hab das mal untersucht, indem ich bisher nicht-gefangene Exceptions nun zentral abfange und in einer Log-Datei speichere. Dabei kam folgendes raus:

Fehlermeldung:
DispatcherUnhandledException: System.IO.IOException: Nicht genügend Quoten, um den angeforderten Dienst auszuführen.

bei System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
bei System.IO.__ConsoleStream.Write(Byte[] buffer, Int32 offset, Int32 count)
bei System.IO.StreamWriter.Flush(Boolean flushStream, Boolean flushEncoder)
bei System.IO.StreamWriter.Write(String value)
bei System.IO.TextWriter.Write(Int32 value)
bei System.IO.TextWriter.WriteLine(Int32 value)
bei System.IO.TextWriter.SyncTextWriter.WriteLine(Int32 value)
bei System.Console.WriteLine(Int32 value)
bei P_Slideshow_Vorabversion.MainWindow.<ImageChangeTimer_Tick>d__24.MoveNext()
--- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde ---
bei System.Runtime.CompilerServices.AsyncMethodBuilderCore.<>c.<ThrowAsync>b__6_0(Object state)
bei System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
bei System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)

Das ganze lässt sich auf diese Codestelle zurückführen, welche im Timer-Tick Event alle 3 Sekunden ausgeführt wird und dem Image-Steuerelement ein neues BitmapImage als Source zuweist:


imageElements[currentImageElement].Source = new BitmapImage(new Uri(System.IO.Path.Combine(mediaDir, imageFiles[currentImageFile])));

Nach kurzer Recherche bedeutet wohl "Nicht genügend Quoten" so viel wie "zu wenig Systemresourcen". Also zu wenig RAM wohl? Das ist aber nicht der Fall. Im laufenden Betrieb genehmigt sich meine Anwendung dauerhaft nur 64Mb RAM. Laut Taskmanager sind auch nur 61% des RAMs belegt, und selbst wenn, dann gäbe es da ja noch die Auslagerungsdatei. Zudem tritt der Fehler nur völlig sporadisch auf. Ich erzeuge da ständig BitmapImage-Objekte, welche ich nie auflöse. Aber der Garbage-Collector sollte sich ja nach einer Weile darum kümmern, die nicht von meinen beiden Image-Steuerelementen gerade geladenen und somit verwaisten BitmapImage-Objekte wieder aus dem RAM zu schmeißen.

Klar, ich könnte jetzt die Exception an entsprechender Stelle adäquat abfangen aber lieber wäre es mir, das Problem an der Wurzel zu packen. Wie kann ich das weiter untersuchen? 🤔

11.12.2016 - 23:57 Uhr

Ich bin gerade auf folgendes gestoßen:

http://stackoverflow.com/questions/34217231/how-to-programmatically-disable-edge-swipe-gesture-of-the-windows-10-tablet-scre

Dieser Code funktioniert scheinbar. Leider verstehe ich überhaupt nicht, was da passiert, würde es aber gerne.

Hat jemand weiterführende Informationen für mich bzw. links, wo ich mich einlesen kann?

11.12.2016 - 23:31 Uhr

Hi,

ich programmiere gerade eine Fullscreen-Anwendung. Jedoch sind für die Touchbedienung die in Windows 10 integrierten Touch-Gesten, wie z.b. das Öffnen des Info-Centers beim Swipe nach links sehr störend.

Nach etwas googeln habe ich hier "System.EdgeGesture.DisableTouchWhenFullscreen" entdeckt, welches mit "Prevents edge gesture behaviors when an application window is active and in full-screen mode (or an owned window is active)." genau die von mir gewünschte Funktion erfüllt.

https://msdn.microsoft.com/en-us/library/windows/desktop/jj553591(v=vs.85).aspx

Leider bin ich noch viel zu unerfahren in der Programmierung um das irgendwie implementiert zu bekommen. Sicher muss ich da irgendwas mit PInvoke machen, leider habe ich nicht mal die Idee, wie ich hier anfangen soll bzw. finde nicht genug Informationen darüber.

Kann mir hier wer helfen? Ich erarbeite mir das auch gerne selbst wenn mich jemand auf die richtigen Informationen stoßen könnte. =)

Gruß, Paul

11.11.2016 - 13:52 Uhr

Also auf dem 1607er System läuft das auch nicht ganz wie gewollt. Der ToggleButton nimmt nun durch Focusable="False" den Fokus anderen Steuerelementen nicht mehr weg. Wenn man ihn mit der Maus bedient erhält er auch keinen Focus mehr. Wenn man ihn jedoch per Toucheingabe mit dem Finger bedient erhält er weiterhin den Focus, bleibt also bläulich gefärbt, nachdem man ihn angetouched hat, auch wenn er eigentlich schon deaktiviert ist. Die Färbung verschwindet erst, wenn man irgendwo anders auf die Oberfläche hintouched.

Deine beiden Tips als Workaround schaue ich mir mal an!

Wo kann man zu WPF bei Microsoft eigentlich Bugreports machen? Oder dürfen das nur ernstzunehmen, professionelle Entwickler und keine Amateure?

08.11.2016 - 19:22 Uhr

Nvm.

Unter Windows10 1607 scheint es zu funktionieren. Mein Tablet mit 1511 ignoriert Focusable="False". 1607 passt auf mein Tablet aus Platzgründen nicht drauf, es hat nur 16GB. Ich versuche jetzt mal das neuste .Net Framework zu installieren, vielleicht hilft das ja.

Edit: Nein, hilft nicht. Scheint wohl ein Problem von Win10 1511 zu sein. Auf meiner VM mit 1607 geht es. Aber seit dem Update von .Net braucht jede noch so kleine WPF-Anwendung 10 Sekunden zum starten. Jedes mal. Das ist doch verrückt. Diese Technologie macht mir den Eindruck, selbst nach 10 Jahren immer noch überhaupt nicht ausgereift zu sein. 🤔 Es ist einfach wahnsinn, über wie viele Bugs ich die letzten Tage gestolpert bin.

Edit2: Ich habe gegoogelt und den Tip mit "NGEN update" von hier befolgt. Das hat geholfen. Irre, dass man zunächst zu solchen Maßnahmen greifen muss, die man irgendwo per Zufall in irgendwelchen Foren findet.

08.11.2016 - 11:12 Uhr

Hi,

für eine Anwendung, welche auf einem Touchscreen-PC laufen wird, programmiere ich gerade eine Oberfläche mit WPF. Ich möchte hier einen ToggleButton nutzen aber es ist für den User sehr irritierend, wenn der ohnehin schon sehr schwach ausgeprägte Farbumschlag des ToggleButtons bei dessen Betätigung auch noch durch den Focus, den er erhält, überlagert wird. Der Zustand lässt sich dabei kaum noch erkennen.

Ich würde generell gerne verhindern, dass Elemente wie Buttons und co. den Focus erhalten. Also habe ich dem ToggleButton die Eigenschaft Focusable="False" gegeben. Auf meinem Entwicklungsrechner mit Windows 7 funktioniert das auch wunderbar. Der Togglebutton erhält auf Klick keinen Focus und nimmt auch anderen Steuerelementen den Focus nicht weg. Auf meinem Windows 10 Touchscreen-PC jedoch zeigt die Eigenschaft überhaupt keine Wirkung.

Warum verhält sich Windows 10 hier anders und wie kann ich nun verhindern, dass der ToggleButton den Focus bekommt?

lg, Paul

08.11.2016 - 10:36 Uhr

Hi,

das Mediaelement macht bei mir ziemlich Probleme. Es ist nun schon ein paar mal der Fall eingetreten, dass nach Abspielen einiger Videos nacheinander das ganze Programm plötzlich sehr langsam und ruckelig wurde. Videos, Animationen, die ganze Oberfläche wurde sehr langsam und schwerfällig. Nach Neustart des Programms ließen sich dann überhaupt keine Videos mehr über das MediaElement abspielen, sie haben einfach nicht geladen.

Nach dem Beenden des Programms ist mir dann aufgefallen, dass noch zwei Instanzen davon im Taskmanager rumhängen, sich aber auch nicht beenden lassen. Sie reagierten einfach nicht auf den Befehl "Task beenden", erzeugten keine CPU-Last und hatten ca. 1MB RAM-bedarf. Generell fühlte sich die gesamte Windows-Oberfläche total ruckelig an, und das, obwohl im Taskmanager kaum RAM oder CPU-Auslastung zu verzeichnen gewesen wären.

Als ich das Tablet neu starten wollte hieß es "Diese App verhindert das Herunterfahren", jedoch ohne eine Bezeichnung der App. Nach dem Klick auf "Trotzdem neu starten" hing das Tablet und ich musste es abwürgen.

Das ist mir nun schon 3 mal innerhalb weniger Stunden Abstand beim Testen meines Programms passiert. Ich habe noch keinen sicheren Weg gefunden, das Verhalten zu reproduzieren. Meistens habe ich aus einer Listbox einfach hektisch Videos ausgewählt, welche beim Anwählen eines Listboxeintrags direkt ins Mediaelement geladen und abgespielt wurden. Irgendwann begann eben die Ruckelei. Ein Memoryleak scheint es nicht zu sein. Sobald ein Video durch ein anderes abgelöst wird wird auch der Speicher wieder freigegeben.

Was kann ich hier tun? V.a. die Tatsache, dass das ganze System noch nach Beendigung des Programms ruckelt deutet hier auf einen tiefergreifenden Bug.

Ich habe gerade mein Programm mal so eingestellt, dass nacheinander automatisch Videos abgespielt werden. Den ganzen Tag lang. Sollte das so zuverlässig durchlaufen wäre es ja ok, aber ein mulmiges Bauchgefühl habe ich dabei trotzdem. Das Programm, welches ich schreibe, ist nicht für mich alleine. Das muss später unter allen Umständen zuverlässig laufen.

//Edit: Nach einem Tag Test: Das Problem tritt seltener auf, aber ich muss davon ausgehen, es irgendwann zwangsläufig passiert. Was kann ich hier tun? Das macht mein ganzes Projekt zunichte.

lg

08.11.2016 - 10:28 Uhr

Hi,

ich habe hier ein kleines Windows 10 Tablet und möchte damit eine Art digitalen Bilderrahmen basteln, der auch Videos abspielen können soll. Hierfür verwende ich das MediaElement.

Die Videos laufen fullscreen. Vornedran wird immer unten immer ein Infotext mit weißer Schrift und halbtransparentem Farbverlauf im Hintergrund angezeigt. Dieser soll bei jedem Videowechsel zuvor mit einer Bewegungsanimation aus dem Bild fliegen und danach wieder einfliegen. Das funktioniert auch.

Wenn ich jedoch der Source des MediaElements eine neue Videodatei zuweise dauert es erst mal 2 Sekunden, bis dieses darin geladen ist. Wenn währenddessen noch eine Bewegungsanimation läuft, ruckelt diese extrem. Das sieht ziemlich unschön aus. Das MediaElement scheint beim Laden den UI-Thread unweigerlich zu blockieren.

Wie kann ich das verhindern?

lg, Paul

08.11.2016 - 10:05 Uhr

Danke 😃 Das probier ich gleich mal!

06.11.2016 - 15:56 Uhr

Hi,

ich habe da eine Idee zu einer Anwendung, bei der ich u.A. Oberflächen deklarativ dynamisch erzeugen möchte. Für den Editor möchte ich Controls per Mauszeiger anordnen können. Dazu müssen diese Controls zwar gerendert werden aber dürfen natürlich keinerlei Interaktionen mit dem Mauszeiger eingehen, d.h. keine Events annehmen usw. Stattdessen soll die gesamte vom Control belegte Fläche reagieren, wenn ich das Control mit dem Mauszeiger in der Gegend rumschieben möchte.

Wie mache ich das? Ich habe schon gegoogelt aber nichts passendes gefunden.

Gibt es da einen speziellen Layoutcontainer für? Oder muss ich irgendwie ein transparentes Objekt über die Controls legen, welches alle Events des darunterliegenden Controls quasi abschirmt?

lg

05.11.2016 - 15:28 Uhr

Hi,

für mein Cloud-Bilderrahmen Projekt, welches ein Windows10 (1511) Tablet als Basis verwenden soll muss ich den Bildschirm per Software ein- und ausschalten können.

Hierfür habe ich ein Codeschnipsel im Internet gefunden, welches mir den Bildschirm ein- und wieder ausschaltet.


        [DllImport("user32.dll")]
        static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);

        private void button1_Click(object sender, EventArgs e)
        {
            SendMessage(this.Handle, 0x0112, 0xF170, 2);
            timer1.Enabled = true;
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            SendMessage(this.Handle, 0x0112, 0xF170, -1);
            timer1.Enabled = false;
        }

Das funktioniert auch, leider gibt es dabei noch ein paar Probleme. Wenn der Connected-Standby aktiv ist dann geht der Bildschirm aus und das Tablet geht ungewollt in den Connected-Standby über, was dazu führt, dass die Ausführung des Programms stoppt und das Tablet nicht wieder aufwacht. Da ich den Connected-Standby nicht unbedingt benötige, habe ich ihn einfach deaktiviert (über die Registry) und neu gestartet. Jetzt schaltet sich der Bildschirm nach der eingestellten Timerzeit zuverlässig auf. Jedoch direkt danach schaltet sich der Bildschirm wieder ab, ohne ersichtlichen Grund?! Zudem ist währenddessen der Touchscreen empfindlich geschaltet. Sobald man ihn berührt geht der Bildschirm wieder an. Das ist nicht unbedingt schlimm aber ich wünschte ich hätt eine Möglichkeit, das abzuschalten.

Hat jemand eine Idee was das soll und wie man das Problem lösen könnte? 🙁

Auf meinem Windows 7 Rechner funktioniert es wie geplant und der Bildschirm bleibt an.

Mein zweites Windows10Pro (1607) Tablet geht komischer weise nicht in den Connected Standby. Dafür begrüßt mich nach dem Wiedereinschalten des Bildschirms in gewohnter Manier der dämliche Sperrbildschirm und direkt danach schaltet sich auch hier der Bildschirm wieder von alleine aus.

Ich habe noch eine weitere Methode gefunden. Diese bewegt zum Aufwecken einfach kurz den Mauszeiger:

        [DllImport("user32.dll")]
        static extern void mouse_event(Int32 dwFlags, Int32 dx, Int32 dy, Int32 dwData, UIntPtr dwExtraInfo);

        private void timer1_Tick(object sender, EventArgs e)
        {
            mouse_event(0x0001, 0, 1, 0, UIntPtr.Zero);
            Thread.Sleep(40);
            mouse_event(0x0001, 0, -1, 0, UIntPtr.Zero);
            timer1.Enabled = false;
        }

Hier bei geht der Bildschirm nach dem Aufwecken nicht wieder von alleine aus. Allerdings ist dann der Mauszeiger sichtbar, und das soll auf Touchscreens auch nicht sein, dass der dann plötzlich dort auftaucht.

Es ist echt verzwickt. Ich frage mich, warum Windows einem da so Steine in den Weg legt 🙄

04.11.2016 - 23:42 Uhr

Ich würde gerne eine Bildergallerie programmieren. Die anzuzeigenden Bilder sind in einer Liste gespeichert, ebenso ihr Aufnahmedatum.

Ich möchte nun alle paar Sekunden ein zufälliges Bild aus dieser Liste auswählen. Die Wahrscheinlichkeit soll jedoch um so höher sein, je neuer das Bild ist, bzw. um so geringer, je älter das Bild ist. Damit erreiche ich, dass vorwiegend die neueren Bilder angezeigt werden aber hin und wieder auch ältere mit dabei sind, so als Erinnerung quasi.

Die Wahrscheinlichkeitsverteilung für die Liste ist durch eine Funktion, welche ich mir schreiben werde, vorgegeben.

Wie programmiere ich die Zufallsauswahl mit dieser Wahrscheinlichkeitsverteilung?

Ich könnte mir vorstellen, dass ich jedem Listeneintrag je nach Wahrscheinlichkeit einen Zahlenbereich zuordne, der um so größer ist, je höher die nominelle Wahrscheinlichkeit des Listeneintrags ist. Dann erstelle ich eine gleichverteilte Zufallszahl, welche mir eine Zufallszahl von 0 bis {summe aller zahlenbereiche} liefert. Dann durchlaufe ich die Liste und schaue, in wessen Listeneintrags Zahlenbereich die Zufallszahl liegt.

z.B.
Bild1 p=50% z=[0...4]
Bild2 p=30% z=[5...7]
Bild3 p=20% z=[8...9]
Bild4 p=10% z=[10]

wenn ich nun eine Zufallszahl s aus dem bereich [0...10] erzeuge, z.B. s=6, dann durchlaufe ich die Liste, bis die Zufallszahl im entsprechenden Zahlenbereich liegt. In diesem Fall bei Bild2.

Besonders geschickt erscheint mir dieser Algorithmus allerdings noch nicht und ich muss mir überlegen, wie ich bei krummen Wahrscheinlichkeitswerten wie p=3,435% usw. den zugeordneten Wertebereich zusammenstelle.

Gibt es noch eine bessere Methode?

lg

27.10.2016 - 23:36 Uhr

Vor einigen Jahren habe ich folgendes Tool entdeckt:

http://always-on-top-maker.de.softonic.com/

Das ist ein kleines Tool, welches im Hintergrund aktiv ist und das Fenster, welches gearde den Fokus hat, bei Betätigen der Tastenkombination Strg+Alt+T auf Topmost=true setzt. Das ist super nützlich für Programme, die man gerne im Vordergrund hätte und die die Funktionalität nicht von selbst schon bereitstellen.

Ich würde so ein Tool gerne in C# nachcoden und mit ein paar Features versehen. Z.b. mehrere Programmfenster per Tastenkombination einzeln in den Vordergrund/Hintergrund schalten können oder oder ein zeitgesteuertes aktivieren der Topmost-Funktion, falls ich mal am Tablet bin und gerade keine Tastatur dran hab und daher die Tastenkombination nicht drücken kann.

Die Frage: wie funktioniert das Tool? Kann man einfach das Handle des gerade aktivierten Fensters raussuchen und es auf Topmost=true setzen? Wo finde ich informationen über die benötigten API-funktionen?

lg

23.04.2016 - 21:44 Uhr

Hi,

ich würde mir gerne eine kleine Software schreiben, mit der ich eine Beamer-Lightshow erzeugen kann. Dabei wird auf einem Beamer ein Bild ausgegeben, welches im Gegenlicht mit Effektnebel einen ähnlichen Effekt wie bei Showlasern erzeugt. Das sieht dann am Ende so aus:
https://www.youtube.com/watch?v=UL7ojzXzCew

Die projizierten Bildinhalte haben dann solchen Charakter: https://www.youtube.com/watch?v=Etu47aLCDh0 oder https://www.youtube.com/watch?v=3X0HbVWnZtA

Zunächst möchte ich feste Szenen einprogrammieren, später könnte das ganze dann sehr variabel gestaltbar werden mit Editor-Oberfläche, in der man sich die Szenen stückchenweise zusammenklicken oder gleich per skriptbasierter Programmierung erstellen kann.

Der Kern einer solchen Software ist natürlich eine Grafikengine, die Projektionsmuster für den Beamer erzeugt. Prinzipiell möchte ich in jeder Szene verschiedenfarbige grafische Formen erzeugen, einfarbig oder mit Farbverlauf. Kreise, Linien, Spiralen, Kurven, Punkte... gestrichelt, punktiert oder durchgezogen. diese möchte ich dann ein- und ausblenden, bewegen, rotieren, skalieren. Verschiedene Szenen sollen gleichzeitig laufen und langsam ineinander überblendet werden. Das ganze soll dabei flüssig auf bis zu 60fps laufen, möglichst sogar mit dem Wiederholrate des angeschlossenen Bildschirms synchron, aber auf jeden Fall absolut ruckelfrei.

Welche Technologie eignet sich hier? GDI erscheint mir etwas zu steif dafür. WPF? Oder eher etwas in Richtung OpenGL? Oder ist das mit dem XNA-Framework ganz einfach zu lösen?

Gruß, Paul

14.01.2016 - 11:33 Uhr

Danke,

das hat geholfen! 🙂

Wo bekomme ich denn die Versionsnummer eigentlich her? Durch googeln habe ich nichts gefunden und die Microsoft Dokumentation sieht mir nach einem Dschjungel aus.

Ist das Windows 8 Theme dann in der Aero2.NormalColor.xaml?

14.01.2016 - 10:42 Uhr

Hi,

um das Look&Feel meiner Anwendung auf Windows 7 Niveau beizubehalten (weil mir das einfach gefällt und ich der einzige Benutzer bin) habe ich in der App.xaml folgendes eingebunden:

    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="/PresentationFramework.Aero;component/themes/Aero.NormalColor.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>

Bei den Verweisen habe ich noch PresentationFramework.Aero hinzugefügt.

Alles gemäß folgender Informationsquelle: http://mrpmorris.blogspot.de/2008/05/using-vista-aero-theme-in-xp-wpf-apps.html

Im Debugger funktioniert das auch wie gewünscht. Wenn ich das Programm jedoch außerhalb von Visual Studio aufrufe gibt es beim Starten einen Fehler.

Fehlermeldung:
Ein Ausnahmefehler des Typs "System.Windows.Markup.XamlParseException" ist in PresentationFramework.dll aufgetreten.

Zusätzliche Informationen: Beim Festlegen der Eigenschaft "System.Windows.ResourceDictionary.Source" wurde eine Ausnahme ausgelöst.

Was mache ich verkehrt?

11.01.2016 - 23:05 Uhr

Also ich nenne das Diskussion 😉 Du argumentierst, ich argumentiere. Wenn meine Argumente Contra-MS sind dann ist das nun mal meine Argumentationsbasis.

Windows 10 ist in weiten bereichen über die Registry anpassbar? Interessant, dazu werd ich mich informieren (Hab ja Win10 bisher nur relativ kurz angetestet). Hast du da evtl. weiterführende Informationen parat?

Dass es über (fremd-)Themes anpassbar ist habe ich wohl leider auch bisher übersehen. Auch da forsche ich gleich mal nach. Geht es hier eigentlich um Themes, die von Microsoft und Schnittstellen des Betriebsystems offiziell unterstützt werden? Meine bisherigen Recherchen ließen nur auf Manipulation des OS durch Fremdsoftware schließen oder eben Themes, die außer Farbe- und Hintergrundbild, sprich, alles was ich auch per Hand so einstellen könnte. nichts neues bieten.

11.01.2016 - 22:55 Uhr

Nunja, Microsoft vertritt ja mit Windows 10 leider eine Friss-oder-Stirb Mentalität. Wo Windows XP noch mehrere grundsätzlich voneinander verschiedene Themes bot konnte man sich unter Windows 7 immerhin noch zwischen Classic, Basic und Aero Theme entscheiden. Seit Windows 8 gibt es allerdings keine Auswahlmöglichkeit und auch keine Anpassungsmöglichkeit mehr. Hier wird alles gleichgeschaltet. Aus Herstellersicht mag das natürlich vorteilhaft sein. Wenn alles gleich ist und alles gleich aussieht ist das für die Softwarepflege und den Support einfacher. Für den User bedeutet es aber eine Einschränkung, keine Wahlmöglichkeit mehr zu haben.

Ich philosophiere aber vermutlich gerade gegen einen Trend, gegen eine Modeerscheinung, die nicht nur Windows 10 betrifft.

Skeuomorphismus ist wohl eher Windows 7.

Flat Design hat sich als Gegenstrom zum Skeuomorphismus entwickelt, bei dem reale Abbildungen (wie eine analoge Uhr, ein analoger Kompass) mit Papiertexturen und Farbverläufen eingesetzt werden, um reale Interaktionen im Interfacedesign nachzubilden. Auf diese Weise werden mögliche Interaktionen wie „einen Knopf drücken“ vom Benutzer sofort erkannt.

11.01.2016 - 22:42 Uhr

Software ist dazu da, dass eine gewisse Aufgabe effizient erledigt wird.
Das ist immer noch der Grundgedanke. Und das System - also Windows - ist eine Plattform, auf dem diese Applikationen laufen.

Das mag prinzipiell richtig sein. Jedoch hat der Computer schon längst Einzug in unser Privatleben erhalten. Und in unserem Privatleben sind wir durchaus um Ästhetik bemüht. Sei es die Inneneinrichtung, die Möbel, die Gardinen, die Wandfarbe, das Auto.. alles ist ästhetisch, alles ist anpassbar. Wieso sollte man dann im Computer zugunsten von Einfachheit und Effizienz auf jegliche Ästhetik und Anpassbarkeit verzichten? Wäre es nicht effizienter, die Wandfarbe der Küche einfach weiß zu lassen anstatt sie weinrot zu streichen? Wäre es nicht günstiger, ein einfaches Rohr anstelle der wohlgeformten, zerbrechlichen, teuren Designer-Vase für die Blume zu nehmen? Wozu überhaupt eine Blume? Solange der PC für mich ein Alltagsgegenstand ist sehne ich mich auch nach der Möglichkeit, diesen nach meinen eigenen Vorstellungen zu gestalten. =)

Nun, ich finde auch die Effizienz von m Flat-Design von Windows 10 nicht gut. Ein nativer Button z.B. ändert seine Farbe beim MouseDown in einem nahezu nicht erkennbaren Maße. Meiner Meinung nach nicht gerade konsequent. Ich verstehe auch nicht, in wie fern die native Oberfläche von Windows 7 im Umkehrschluss "ineffizient" sein soll. Aus Sicht der Renderingperformance? Aus Sicht der Geschwindigkeit, mit der man Steuerelemente als solche erkennen sowie ihren Zustand beurteilen kann? Tut mir leid, gerade da, finde ich, schneidet das Flat-Design von Windows 10 mieserabel ab.

11.01.2016 - 22:17 Uhr

Habe dem ganzen mal etwas den Druck rausgekommen durch einige Editierungen 🙂
Der Umstieg auf Windows 10 wird in ein paar Jahren zwangsläufig kommen, denn der Support für Windows 7 endet irgendwann. Linux/Mac sind natürlich keine direkten Alternativen. Das Design kann man in Windows 10 leider weniger denn je anpassen. Hier hat Microsoft konsequent sämtliche Einstellungsmöglichkeiten entfernt.

Interessant sind vor allem die Stimmen der Befürworter für mich. Gewähren neue Einblicke in neue Ansichtsweisen, auch wenn man nicht immer gleichermaßen betroffen ist. 😉

Ich z.B. fand den "Aero-Quatsch" schon immer sehr ansprechend. Ein derart Leistungsfähiger Computer kann ruhig auch einen gewissen Sinn für Ästhetik ansprechen, sowohl Design als auch Glass-Effekt fand ich in Windows 7 hervorragend umgesetzt und ich verneige mich auch heute noch vor dieser Leistung. In Windows 8/10 wurde dieses "Feature" dann wieder komplett entfernt. Dem Windows 8 hätte ich wohl noch am ehesten "Ästhetik durch Einfachheit" zugesprochen, Win10 hingegen sieht für mich einfach schlecht und lieblos umgesetzt aus (ich rede hier vor allem vom nativen Look der Steuerelemente in den Anwendungen, wobei sich das ja nahezu durch das gesamte OS durchzieht).

11.01.2016 - 22:00 Uhr

Nunja.. es wirkt zugegeben erst einmal wie Gemecker. Allerdings möchte ich damit eine kleine Diskussion anstoßen und erfahren, wie ihr das so seht. Vielleicht stehe ich ja nicht alleine mit meiner Ansicht.

Gegen Flat- oder Material-Design habe ich grundsätzlich nichts. Im Gegenteil, ich finde das bei Windows 8 sehr sehr chic umgesetzt. Windows 10 übertreibt es hierdoch deutlich imho.