2014-09-09 4 views
1

У меня есть игра с несколькими противниками, каждая из которых работает в своей нити для перемещения и рисования. Враги нарисованы на панели, и поэтому их потоки должны получить доступ к Графику панели. Я защитил вызов CreateGraphics, используя Lock, и когда я хочу ReleaseHdc Графика панели, я получаю System.ArgumentException, хотя я вызываю метод ReleaseHdc без каких-либо аргументов. Вот соответствующий код (p является эталонным панель передается в качестве статической переменной и указывает на правильный контроль):Graphics.ReleaseHdc() бросает ошибку ArgumentException с многопоточными экземплярами

//Member region 
internal Bitmap Img = new Bitmap(Image.FromFile(@"Enemy.png"), Size); 
internal static readonly object _Lock = new object(); 

//from enemy's custom Move() method 
lock (_Lock) 
{ 
    Graphics gfx = p.CreateGraphics(); 
    gfx.DrawImage(Img, Location); 
    gfx.ReleaseHdc(); // gfx.Dispose() works here      
} 

Кто-нибудь есть идея, почему я получаю эту ошибку и/или как это исправить, учитывая многопоточный доступ, который мне нужен, чтобы нарисовать каждый элемент на одной панели в своем потоке?

[Редактировать]

gfx.Dispose() Использование вместо ReleaseHdc() сделал трюк. Результат, хотя и не удовлетворительный, потому что я получаю очень неустойчивое изображение с мерцающими врагами. Вероятно, это проблема, связанная с их неоднократным повторением и не связанная с моим вопросом - или существует ли связь между этой проблемой и как я обрабатываю несколько потоков?

+0

Вы играете в очень опасную игру. Этот замок, безусловно, был хорошей идеей, однако вы не применили тот же самый замок в методе OnPaint() панели. Выведите собственный класс из панели и переопределите OnPaint() и OnPaintBackground(). Использование ReleaseHdc() было неправильным, вы должны использовать Dispose() вместо этого. Могу работать, не надейтесь. –

+0

Есть ли конфликт в создании нескольких экземпляров «Graphpics» элемента управления? Может ли быть только одно в существовании одновременно, так что каждый нить не может создать свой собственный? Я перерабатываю свою программу на данный момент, чтобы получить «Панель», но было бы хорошо знать в любом случае. – Johannes

+0

Создание экземпляров графики в нескольких потоках в порядке. Использование его свойств, таких как DpiX, прекрасно. Такие вещи, как MeasureString(), прекрасны. Фактически, используя их для рисования на экране, это опасная игра. Также очень сложно рассуждать о том, что вы получите, когда несколько потоков будут отображаться в одной и той же области экрана, конечный результат всегда непредсказуем. –

ответ

0

Не следует ли звонить gfx.GetHdc(), если вы хотите позвонить gfx.ReleaseHdc()?

Я думаю, что ваш код должен выглядеть следующим образом:

lock (_Lock) 
{ 
    using (var gfx = p.CreateGraphics()) 
    { 
     gfx.DrawImage(Img, Location); 
    } 
} 

Я также считаю, вызов CreateGraphics() сам по себе является немного подозрительным. Я ожидаю, что объект Graphics будет поставляться до вместо этого создан код чертежа от.

+0

Это все еще вызывает одно и то же исключение. Но см. Мое редактирование выше - использование Dispose() работает. – Johannes

+1

@Johannes Но код, который я написал выше, использует Dispose()!Это то, что делает 'использование' ... И если он выдает одно и то же исключение, это означает, что проблема не в' ReleaseHdc() ', поскольку код, который я написал, даже не назвал его ... –

+0

О, извините, Я этого не понимал и не удалял 'ReleaseHdc()'! Работает точно так же, как печатать в утилите вручную, спасибо! О другом комментарии: есть ли хороший способ предоставить Panel.CreateGraphics для каждого потока? Я полагаю, устанавливая его с помощью статической переменной и защищая его с помощью Lock, должен работать? Я попробовал это до очень короткого времени и получил ошибку, поэтому я попытался создать его таким образом. – Johannes