C#System.InvalidOperationException:Object目前正在其他地方使用

时间:2013-01-19 12:45:08

标签: c# multithreading gdi+ game-loop

我已经看过同一主题的问题,但无法弄清楚如何解决这个问题。在我的游戏中,我使用两个线程一个Logic线程和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();
}

我该如何解决这个问题?已经尝试在渲染循环上粘贴逻辑循环,这使我的游戏变得如此缓慢。

由于

1 个答案:

答案 0 :(得分:6)

“两个线程”当然是问题所在。它们不允许两个线程同时访问 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);
        }
    }

其余的看起来也不健康,你没有确定你在两个线程之间正确地打乒乓,并且很不清楚什么线程拥有该窗口。

相关问题