2016-06-04 21 views
0

Ich habe versucht, animierte Flut füllen (Scanline-Algorithmus) mit Schlaf in vb. So wird die Reihenfolge der Pixel angezeigt. Es wird für ein wenig arbeiten, aber dann wird es zurückgeben Objekt zur Zeit an anderer StelleAnimation von flood füllen vb return object wird derzeit an anderer Stelle verwendet thread.sleep

mein Code verwendet wird, Dies ist

Sub AnimatedRFRecursive(ByVal P As Point, ByVal C0 As Color, ByVal C1 As Color) 

    Dim i, xL, xR As Integer 
    Dim a As Point 
    i = P.X 
    While (i >= 0 AndAlso BMP.GetPixel(i, P.Y) = C0) 
     Thread.Sleep(10) 
     BMP.SetPixel(i, P.Y, C1) 
     PictureBox1.Invoke(New Action(Sub() PictureBox1.Image = BMP)) 
     i -= 1 
    End While 
    xL = i + 1 
    i = P.X + 1 
    While (i < 500 AndAlso BMP.GetPixel(i, P.Y) = C0) 
     Thread.Sleep(10) 
     BMP.SetPixel(i, P.Y, C1) 
     PictureBox1.Invoke(New Action(Sub() PictureBox1.Image = BMP)) 
    End While 
    xR = i - 1 
    For i = xL To xR 
     If (P.Y < 349 AndAlso BMP.GetPixel(i, P.Y + 1) = C0) Then 
      a.X = i 
      a.Y = P.Y + 1 

      AnimatedRFRecursive(a, C0, C1) 
     End If 
     If (P.Y > 0 AndAlso BMP.GetPixel(i, P.Y - 1) = C0) Then 
      a.X = i 
      a.Y = P.Y - 1 
      AnimatedRFRecursive(a, C0, C1) 
     End If 
    Next 
End Sub 

Dies ist, wie ich es nennen

Dim thr As New Threading.Thread(Sub() AnimatedRFRecursive(point, C, Color)) 
thr.Start() 

Bitte sagen Sie mir, wo tat Ich mache falsch oder wenn Sie eine andere Methode haben, die auch funktioniert. Danke

+0

Erhalten Sie den Fehler, wenn Sie die Picture1.Invoke Zeilen auskommentieren? – ChicagoMike

+0

habe ich nicht. Aber die Bildfüllung wird nicht angezeigt – NatJ

+0

Sie werden nicht viel für diesen Code verwenden. Es schlägt fehl, da auf Bitmap von jeweils nur einem Thread zugegriffen werden kann. Der zweite Thread, der darauf zugreift, ist der UI-Thread, wenn der PictureBox-Inhalt neu gezeichnet werden muss. Ziemlich zufällig, aber ziemlich wahrscheinlich. Normalerweise würden Sie das Schlüsselwort * lock * verwenden, um dies zu verhindern, aber Sie können diese Anweisung nicht in den Code von PictureBox einfügen. Du musst dein eigenes machen. Verwenden Sie einfach keinen Thread, es hilft überhaupt nicht. Verwenden Sie stattdessen einen Timer. –

Antwort

1

Sie haben mehrere Threads, die auf dasselbe Objekt (BMP) zugreifen müssen. Dies erfordert, dass Sie den Zugriff auf das BMP-Objekt synchronisieren.

Bitte beachten Sie, dass Ihr ursprünglicher Code zwei magische Zahlen (500 und 349) hat, von denen ich annahm, dass sie der Breite und Höhe der Bitmap entsprechen. Ändern Sie die Verwendung der Variablen im folgenden Code, wenn diese Annahme falsch ist.

Private BMP As Bitmap 
Private BMPKey As New Object 
Private Sub UpdatePictureBox() 
    PictureBox1.Invoke(Sub() 
           SyncLock BMPKey 
            Dim oldBM As Image = PictureBox1.Image 
            PictureBox1.Image = New Bitmap(BMP) 
            If oldBM IsNot Nothing Then oldBM.Dispose() 
           End SyncLock 

           End Sub) 

End Sub 

Private Function GetBMPPixel(x As Int32, y As Int32) As Color 
    SyncLock BMPKey 
     Return BMP.GetPixel(x, y) 
    End SyncLock 
End Function 

Private Sub SetBMPPixel(x As Int32, y As Int32, c As Color) 
    SyncLock BMPKey 
     BMP.SetPixel(x, y, c) 
    End SyncLock 
End Sub 

Sub AnimatedRFRecursive(ByVal P As Point, ByVal C0 As Color, ByVal C1 As Color) 

    Dim i, xL, xR As Integer 
    Dim a As Point 
    i = P.X 
    Dim width As Int32 
    Dim height As Int32 
    SyncLock BMPKey 
     width = BMP.Width  ' original code magic number of 500 
     height = BMP.Height ' original code magic number of 349 
    End SyncLock 
    While (i >= 0 AndAlso GetBMPPixel(i, P.Y).ToArgb = C0.ToArgb) 
      Thread.Sleep(10) 
      SetBMPPixel(i, P.Y, C1) 
      UpdatePictureBox() 
      i -= 1 
    End While 
    xL = i + 1 
    i = P.X + 1 
    While (i < width - 1 AndAlso GetBMPPixel(i, P.Y).ToArgb = C0.ToArgb) 
      Thread.Sleep(10) 
      SetBMPPixel(i, P.Y, C1) 
      UpdatePictureBox() 
    End While 
    xR = i - 1 
    For i = xL To xR 
      If (P.Y < height - 1 AndAlso GetBMPPixel(i, P.Y + 1).ToArgb = C0.ToArgb) Then 
       a.X = i 
       a.Y = P.Y + 1 

       AnimatedRFRecursive(a, C0, C1) 
      End If 
      If (P.Y > 0 AndAlso GetBMPPixel(i, P.Y - 1).ToArgb = C0.ToArgb) Then 
       a.X = i 
       a.Y = P.Y - 1 
       AnimatedRFRecursive(a, C0, C1) 
      End If 
    Next 
End Sub 
+0

Es funktioniert für eine Weile, aber danach gibt es diese "Bitmap-Region ist bereits gesperrt" – NatJ

+0

Seltsamerweise kann es von der zweiten während der for-Schleife springen – NatJ

+0

@NatJ - Ich habe eine kleine Änderung an den Code. Probieren Sie es aus. Starten Sie auch mehrere Threads, die 'AnimatedRFRecursive' aufrufen? Wenn dies der Fall ist, muss die Logik Sperren implementieren, um den gleichzeitigen Zugriff zu verhindern. – TnTinMn