Ş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));
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
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. –
@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