2016-06-04 2 views
0

Я попытался сделать анимированную заливку заливки (алгоритм scanline), используя сон в vb. Таким образом, будет отображаться порядок окрашивания пикселей. Она будет работать на немного, но тогда он будет возвращать объект в настоящее время используется в другихСоздание анимации заливки заливки в объект возврата vb в настоящее время используется в другом месте, используя thread.sleep

Это мой код

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 

Это, как я это называю

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

Пожалуйста, скажите мне, где сделал Я ошибаюсь или у вас есть другой метод, который работает. Спасибо

+0

Получаете ошибку, если вы закомментируете строки Picture1.Invoke? – ChicagoMike

+0

Я этого не делал. Но заполнение картинки не отображается – NatJ

+0

У вас мало пользы для этого кода. Он терпит неудачу, поскольку к Bitmap можно получить доступ только по одному потоку за раз. Второй поток, который обращается к нему, представляет собой поток пользовательского интерфейса, происходит, когда содержимое PictureBox необходимо перекрасить. Довольно случайный, но, скорее всего, произойдет. Обычно вы использовали ключевое слово * lock *, чтобы это не происходило, но вы не можете вставить этот оператор в код PictureBox. Вы должны сделать свой собственный. Просто не используйте нить, это совсем не помогает. Вместо этого используйте таймер. –

ответ

1

У вас есть несколько потоков, которым необходимо получить доступ к одному и тому же объекту (BMP). Для этого вам потребуется синхронизировать доступ к объекту BMP.

Обратите внимание, что ваш исходный код имеет два магических номера (500 и 349), которые, как я предполагал, соответствуют ширине и высоте растрового изображения. Измените использование переменных в приведенном ниже коде, если это предположение неверно.

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

Он работает некоторое время, но после этого он возвращает это «Растровая область уже заблокирована» – NatJ

+0

Сверх того, он может перепрыгивать со второго, а в цикл for – NatJ

+0

@NatJ - Я сделал небольшое изменение кода. Попробуйте. Кроме того, вы запускаете несколько потоков, которые вызывают «AnimatedRFRecursive»? Если это так, логике потребуется реализовать блокировки для предотвращения параллельного доступа. – TnTinMn

Смежные вопросы