Laden...

[erledigt] DeadLock, aber warum?

Erstellt von HomerJ vor 14 Jahren Letzter Beitrag vor 14 Jahren 1.228 Views
H
HomerJ Themenstarter:in
20 Beiträge seit 2009
vor 14 Jahren
[erledigt] DeadLock, aber warum?

Hallo leute,

eigentlich wollte ich mich nur mal mit Layered Windows unter C# versuchen und auf einmal komme ich zu einem "deadlock", der für mich absolut unerklärlich ist.



      void Form1_Click(object sender, System.EventArgs e) {
         Bitmap b = new Bitmap(300, 400, PixelFormat.Format32bppArgb);

         Graphics g = Graphics.FromImage(b);

         using (Brush RedTransparentBrush = new SolidBrush(Color.FromArgb(100, Color.DarkRed)))
            g.FillRectangle(RedTransparentBrush, 0, 0, b.Width, b.Height);

         lock (_updateWindowLock) // BAM! blockiert das gesamte Programm!
            SetBitmap(b);

      }

      private void FadeThreadMethod(object objStartArgs) {
         int[] startArgs = (int[])objStartArgs;
         lock (_updateWindowLock) {
            if (startArgs[0] < startArgs[1]) { // Fade in!
               for (int op = startArgs[0]; op < startArgs[1]; op += startArgs[2]) {
                  Invoke(new MethodInvoker(delegate() { SetOpacity((byte)op); }));
                  Thread.Sleep(startArgs[3] / (startArgs[1] - startArgs[0]) * startArgs[2]);
               }
            } else if (startArgs[0] > startArgs[1]) { // Fade out!
               for (int op = startArgs[0]; op > startArgs[1]; op -= startArgs[2]) {
                  Invoke(new MethodInvoker(delegate() { SetOpacity((byte)op); }));
                  Thread.Sleep(startArgs[3] / (startArgs[0] - startArgs[1]) * startArgs[2]);
               }
            }
            MessageBox.Show("fertig");
         }
      }

Sobald ich klicke, während er FadeIn macht, endet dies in einer Blockade der FadeThreadMethod (die parallel läuft).

Ich wollte nur nicht, das während des FadeIns die farbe geändert werden kann (sei dahingestellt ob das sinnvoll ist).

Ich habe Monitor.TryEnter mit 2000 ms timeout versucht:

Programm blockiert 2 sekunden, und fade rennt dann weiter!

Rot wird der hintergrund allerdings nur, wenn ich das form NACH dem faden anklicke.

Bitte kein kommentar zu den fehlenden casts bei der division, das ist jetzt nebensächlich 😃

Gelöschter Account
vor 14 Jahren

ohne den code jetzt näher betrachtet zu haben, kann cih dir mitteilen das du deinen gewünschten effekt auch hiermit erreichen kannst:

	[AnimateWindow ](http://www.mycsharp.de/wbb2/thread.php?threadid=23991)
H
HomerJ Themenstarter:in
20 Beiträge seit 2009
vor 14 Jahren

danke für deine schnelle antwort!

naja erstens gehts mir mal um das threading, jetzt will ichs wissen 😄

und zweitens, animatewindow geht afaik nicht bei "per-pixel-alpha"-layered windows, oder?

99 Beiträge seit 2006
vor 14 Jahren

ich sehe keinen Aufruf der Methode FadeThreadMethod, wo und wie wird sie aufgefuren?

Form1_Click scheint unkomplett zu sein

Es gibt
lock (_updateWindowLock) // BAM! blockiert das gesamte Programm!

aber es gibt kein unlock, wie hier

lock(xxxx)
{
sicheres code
}

Grüße
Pawel

H
HomerJ Themenstarter:in
20 Beiträge seit 2009
vor 14 Jahren

lock(_updatewindowLock) EINE_ANWEISUNG;
beendet den block nach der anweisung, wodurch monitor.Exit aufgerufen wird.

FadeThreadMethod wird natürlich im Konstruktor über den Thread mit .Start() aufgerufen.

179 Beiträge seit 2006
vor 14 Jahren

Mach mal aus den beiden Invokes, jeweils ein BeginInvoke.

Invoke wartet ja bekanntlich darauf, dass der GUI Thread bereit ist eine Aktion auszuführen und führt die die Aktion dann im GUI Thread und warted bis diese fertig ist.
Nun ist aber dein GUI Thread Blockiert und und wartet darauf das die Thread-Methode den Lock aufhebt. Ergo Deadlock.

Irgendwo gabs hier ma

H
HomerJ Themenstarter:in
20 Beiträge seit 2009
vor 14 Jahren

omg...

danke vielmals..

mit begininvoke gehts bei näherer überlegung genau so wenig (von der anzeige her) aber der deadlock is weg!

*verbeuge*

H
HomerJ Themenstarter:in
20 Beiträge seit 2009
vor 14 Jahren

Sodala, weiter im Text..

Habe das ganze jetzt so umgeschrieben, blockiert aber ebenfalls wieder (siehe comment)

      void Form1_Click(object sender, System.EventArgs e) {
         Bitmap b = new Bitmap(300, 400, PixelFormat.Format32bppArgb);

         Graphics g = Graphics.FromImage(b);

         using (Brush RedTransparentBrush = new SolidBrush(Color.FromArgb(100, Color.DarkRed)))
            g.FillRectangle(RedTransparentBrush, 0, 0, b.Width, b.Height);

         ThreadInvoke(delegate() {
            lock (_updateWindowLock) // blockert gesamte Anwendung
               SetBitmap(b);
         });
      }

      private void FadeThreadMethod(object objStartArgs) {
         int[] startArgs = (int[])objStartArgs;
         lock (_updateWindowLock) {
            if (startArgs[0] < startArgs[1]) { // Fade in!
               for (int op = startArgs[0]; op < startArgs[1]; op += startArgs[2]) {
                  Invoke(new MethodInvoker(delegate() { SetOpacity((byte)op); }));
                  Thread.Sleep(startArgs[3] / (startArgs[1] - startArgs[0]) * startArgs[2]);
               }
            } else if (startArgs[0] > startArgs[1]) { // Fade out!
               for (int op = startArgs[0]; op > startArgs[1]; op -= startArgs[2]) {
                  Invoke(new MethodInvoker(delegate() { SetOpacity((byte)op); }));
                  Thread.Sleep(startArgs[3] / (startArgs[0] - startArgs[1]) * startArgs[2]);
               }
            }
         }
      }

      private void ThreadInvoke(MethodInvoker d) {
         Thread t = new Thread(delegate() { Invoke(d); });
         t.Start();
      }

Meiner Ansicht nach müsste jetzt der GUI Thread frei sein, oder?#

edit: man bin ich dumm, klar das wenn das lock innerhalb Invoke aufgerufen wird, das selbe rauskommt 😃

Lösung:


      private void ThreadInvoke(object LockObject, MethodInvoker d) {
         Thread t = new Thread(delegate() { lock(LockObject() Invoke(d); });
         t.Start();
      }

und eben den aufruf anpassen (ohne lock im delegate)

kann geschlossen werden =)