0

同じトピックに関する質問を既に見ましたが、この問題を解決する方法がわかりませんでした。私のゲームでは、1 つのLogicスレッドと 1 つのスレッドの 2 つのスレッドを使用していUIます。これは私が抱えている問題です

System.InvalidOperationException: Object is currently in use elsewhere.
   at System.Drawing.Graphics.FromImage(Image image)
   at GECS.Core.Game.UpdateLoop() in c:\Us....ore\Game.cs:line 82
   at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ThreadHelper.ThreadStart()

UIスレッドでのみレンダリングしていました。これが私のレンダリングループです。コンストラクターに直接配置しました。

while (true) {
    if (!Created) {
        break;
    }
    if (Win32.PeekMessage(out msg, IntPtr.Zero, 0, 0, (uint)Win32.PM.REMOVE)) {
        if (msg.message == (uint)Win32.WindowsMessage.WM_QUIT) {
            break;
        } else {
            Win32.TranslateMessage(ref msg);
            Win32.DispatchMessage(ref msg);
        }
    } else {
        Text = Global.TITLE;
        now = GetCurrentTime();
        Graphics front = Graphics.FromHwnd(Handle);
        front.DrawImage(backBuffer, 0, 0);
        front.Dispose();
    }
}

そして私の論理ループ

while (Created) {
    now = GetCurrentTime();
    while (now > game_time) {
        elapsedTime = 1000/Global.ACTUAL_STEPS_FOR_SECOND;
        Update(elapsedTime);
        Map.UpdateObjects(elapsedTime);
        game_time += step_size;
    }
    Graphics g = Graphics.FromImage(backBuffer);   // This line is error
    g.Clear(Color.WhiteSmoke);
    Render(g);
    g.Dispose();
}

どうすればこの問題を解決できますか? ロジック ループをレンダー ループの上に貼り付けようとしたため、ゲームが非常に遅くなりました。

ありがとう

4

1 に答える 1

5

もちろん、「2つのスレッド」が問題です。両方のスレッドが同時にbackBufferにアクセスすることはできません。これを防ぐには、ロックを使用する必要があります。だいたい:

private object bufferLock = new object();
...
    using (var front = Graphics.FromHwnd(Handle)) {
        lock (bufferLock) {
            front.DrawImage(backBuffer, 0, 0);
        }
    }

    lock (bufferLock) {
        using (var g = Graphics.FromImage(backBuffer) {  // No more error
            g.Clear(Color.WhiteSmoke);
            Render(g);
        }
    }

残りの部分もそれほど健全に見えません。2 つのスレッド間で適切にピンポンを行っていることを確認していないため、どのスレッドがウィンドウを所有しているかが非常に不明確です。

于 2013-01-19T13:30:25.557 に答える