2012-04-28 1 views
1

애니메이션을위한 몇 초마다 별도로 다시 그려야하는 같은 형식의 두 객체로 게임을 만들었습니다. 별도의 스레드에 하나 있습니다. 때마다 그래픽 객체가 이미 사용 중임을 나타내는 오류가 발생합니다.C#에서 그래픽 객체를 동시에 사용하는 동안 오류가 발생 했습니까?

Graphics sprite1 = this.CreateGraphics(); 
Graphics sprite2 = this.CreateGraphics(); 

는 그때 적절한 방법으로 이러한 개체를 전달할 : 나도 같은 양식의 2 개 그래픽 객체를 구성 때문에 오류가 적게 나타납니다. 이것은 아마도 매우 위험한 행위라는 점에 두려워합니다. 이 문제를 해결하는 데 도움을 주시면 감사하겠습니다.

+0

당신은 다른 스레드에 그 그래픽 객체를 부여한다는 말입니까? 얼마나 많은 (심지어 1 개의) 그래픽 객체를 만들지에 관계없이 파트가 혼자서하는 것이 안전하지 않다는 것을 확신합니다. –

+0

예. 그들은 다른 스레드로 보내집니다. 같은 시간에 애니메이션을 계속하려면 객체가 필요합니다. 하나는 항상 다시 그려지며, 다른 하나는 사용자가 움직이면 다시 그려집니다. 슬프게도, 동시에 발생합니다. 내가 뭘 권하고 싶니? – codeblooded

+0

내가 뭘할지 모르지만 .NET Framework의 컨트롤에 대한 멀티 스레드 액세스가 지원되지도 안전하지도 않습니다. –

답변

3

일반적으로 게임은 멀티 스레드가 아니지만 게임 루프가 있습니다. 매 반복마다 모든 객체의 위치가 현재 시간에 따라 다시 계산됩니다. 그런 다음 다시 그려집니다.

멀티 스레드 방식으로 계산을 수행하는 것이 좋습니다. 그러나 모든 드로잉은 게임 루프 내부의 주 스레드 (소위 UI 스레드)에서 발생해야합니다. 위키 백과에 Game programming에서


장 참조 "게임 구조".

3

예, 문제가 있습니다. 실제 오류는 GDI + 내부의 코드에서 발생합니다. 동일한 코드가 여러 스레드에서 사용될 수 없습니다. 그러나 더 깊은 문제이지만 윈도우를 직접 참조하는 Graphics 객체를 생성하고 있습니다. 기본 Windows 개체는 장치 컨텍스트의 핸들 인 HDC입니다. 장치 컨텍스트는 스레드로부터 안전하지 않습니다. 재난은 때로는 그림 유물, 교착 상태 및 접근 위반입니다.

FromImage() image에 의해 생성 된 Graphics 객체가 다른 비트 맵에서 생성되거나 두 개의 스레드가 동시에 같은 Graphics 객체를 사용하려고 시도하지 않는 한 작업하도록 만듭니다. 그건 게임 프로그래밍에별로 도움이되지 않을 것입니다.

32bppPArgb 픽셀 형식으로 비트 맵을 만들어 빠르게 그릴 수있는 스프라이트를 만들 수 있습니다. 대부분의 컴퓨터에서 다른 형식보다 10 배 더 빠릅니다. 일반 GDI +로 푸시 할 수있는 한, 다음 단계는 비디오 메모리에 상주하며 GPU 하드웨어를 사용하는 비트 맵을 사용하는 그래픽 라이브러리를 사용하는 것입니다. 이러한 라이브러리에 대한 인기있는 관리되는 래퍼는 XNA, SlimDX 및 SharpDX입니다.

1

위에서 언급했듯이 this.CreateGraphics()은 실제로 전체 양식 자체 인 동일한 그래픽 객체에 대한 참조를 작성합니다. 이슈 스레딩을 제외하고는 드로잉이 다른 스크린을 표현하기 위해 사전 정의 된 드로잉 영역을 벗어나지 않도록함으로써 이론적으로는 코드에서이를 처리 할 수 ​​있습니다. 이것은 약간의 하드 코딩을 필요로하고 내 스타일이나 선호도가 아닙니다.

이럴 훨씬 더 나은 방법은 다음

Image screen1 = new Bitmap(100, 100); // (width, height) 
    Image screen2 = new Bitmap(100, 100); // (width, height) 

는 별도로 각 이미지의 표면에 그리는 "각 보유하는 이미지 뷰어와 같은 간단한 일을 사용할 수 있습니다 ... 메모리에 두 개의 이미지 객체를 생성하는 것입니다 보기 "...

private void DrawGame() 
    { 
     DrawSprite1(Graphics.FromImage(screen1)); 
     DrawSprite2(Graphics.FromImage(screen2)); 
    } 
    public void DrawSprite1(Graphics g) 
    { 
     g.FillEllipse(Pens.Blue, screen1.GetBounds()); 
    } 
    public void DrawSprite2(Graphics g) 
    { 
     g.FillRect(Brushes.Red, screen2.GetBounds()); 
    } 

은 물론, 문제는이 문제에 접근하는 유일한 방법은 아니지만, 자신의 솔루션으로 당신에게 영감을 참조 표기하고 있습니다. :)