2016-04-05 17 views
-1

Şu anda pictureBox'la formum var. Form, imleç etrafındaki dairelere giden 3 orbital çizer. Her 'Orbital', orbitalin özel parametrelerine bağlı olarak her 1 derece rotasyonda kendi iplik güncelleme pozisyonuna sahip ayrı bir nesnedir. Ana programda, en hızlı olana bağlı olarak her bir yörünge için çizim işlevini çağırıyorum, bu yüzden kekemem.C# çok iş parçacıklı - paylaşılan Bitmap, kilitler ve semaforlar

Şimdi, her şey yolunda, ancak Bitmap'e aynı anda yalnızca bir iş parçacığı tarafından erişilemediğini alamıyorum. Semafor/kilit ekleme, "şu anda başka bir yerde kullanım" hatasını geciktirir, ancak bunu engellemez. Kilit (/ semafor) yapıcıdaki her Orbital'e geçirilir. İşte

görünüm yenilenmesi iplik denilen güncellemeniz için kod:

private void UpdateDisplay() 
    { 
     // get fresh display 
     Lock.AcquireWriterLock(-1); 
      Display = (Bitmap)(Background.Clone()); 
     Lock.ReleaseWriterLock(); 
     // draw all orbitals 
     foreach (Orbital item in Orbitals) 
     { 
      item.Draw(Display); 
     } 
     // update the display 
     Lock.AcquireWriterLock(-1); 
      pictureBox1.Image = Display; 
     Lock.ReleaseWriterLock(); 
    } 

Ve bu nesne Orbital Kurası yöntemidir:

public void Draw(Bitmap bitmap) 
    { 
     // draw a square 
     int maxX = OrbitalX + OrbitalSizeRadius; 
     int maxY = OrbitalY + OrbitalSizeRadius; 
     for (int i = OrbitalX - OrbitalSizeRadius; i < maxX; i++) 
     { 
      for (int j = OrbitalY - OrbitalSizeRadius; j < maxY; j++) 
      { 
       Lock.AcquireWriterLock(-1); 
        // check for eventual offscreen pixels 
        if (BoundaryControl.Check(i, j, bitmap.Width, bitmap.Height)) 
        { 
         bitmap.SetPixel(i, j, OrbitalColor); 
        } 
       Lock.ReleaseWriterLock(); 
      } 
     } 
    } 

Ben kilitleme/bekleme, yalancı olduğunu düşünmüş atomik, ama görünüşünden, yanlış anlamadığım sürece, öyle değil.

DÜZENLEME:

Hata hakkında daha fazla ayrıntı. Her zaman pictureBox1.Image = Display; numaralı hattan rastgele zamanlarda dışarı atlar: bir spinin yarısından sonra tam spine kadar. Orbital içinde kilit taşıma konusunda

An unhandled exception of type 'System.InvalidOperationException' occurred in System.Drawing.dll 

Additional information: Object is currently in use elsewhere. 

Kodu: Form sınıfının içinde

// declaration 
private ReaderWriterLock Lock; 

// constructor 
public Orbital(int radius, double speed, int sizeRadius, Color color, int startingRotation, bool counterClockwise, ReaderWriterLock thelock) 
    { 
     /* 
     * bunch of assigns 
     */ 
     Lock = thelock; 
    } 

: çözüldü

// declaration 
private ReaderWriterLock Lock; 

// initialization 
Lock = new ReaderWriterLock(); 

// passing to Orbital as an argument 
// Orbitals is an ArrayList 
Orbitals.Add(new Orbital(100, 10, 5, Color.IndianRed, 0, false, Lock)); 
+0

Aldığınız hata nedir ve bir satır nedir? '' şu anda başka bir yerde kullanımda ''çok yardımcı olmuyor .. Sadece 1 kilit kullandığınızdan emin misiniz? Belki de yanlışlıkla 3 kilit yaptı ve aynı iş parçacığı yerine her bir iş parçacığına farklı bir tane verdiniz. – Quantic

+1

Sadece meraktan dolayı, paylaşılan bir bitmap'e yazarken birden fazla iş parçacığı seçmenin belirli bir nedeni var mı? Sadece bu yaklaşımın oldukça atipik olduğunu soruyorum. En yaygın çözüm, veri yapınız boyunca tek bir çizim parçasının yürümesi ve gerektiğinde her şeyi yeniden çizmektir. –

+0

@LeeHiles, Belirli bir alt sınıf çizim yöntemi almak istediğimde Orbital içine Draw tutmak istedim. Ayrıca tüm bilgileri ana programa atmak zorunda kalacağım, ama bu küçük. Bilmiyorum, iyi bir fikir gibi görünüyordu. – Whazz

cevap

0

Gizem, Kilitler mükemmel iyi çalışır. Ekran Paylaşımı gerçekten bir problemdi, ancak çözme, aynı hatayı alan başka bir gizli soruyu 'açığa çıkardı'.

İlgili konular