【问题标题】:C# System.InvalidOperationException: Object is currently in use elsewhereC# System.InvalidOperationException:对象当前正在其他地方使用
【发布时间】:2013-01-19 12:45:08
【问题描述】:

我已经看到关于同一主题的问题,但不知道如何解决这个问题。在我的游戏中,我使用两个线程一个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();
}

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

谢谢

【问题讨论】:

    标签: c# multithreading gdi+ game-loop


    【解决方案1】:

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

    其余的看起来也不那么健康,你没有确保你在两个线程之间正确地乒乓球,并且非常不清楚哪个线程拥有窗口。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-14
      • 2010-09-19
      • 2010-11-06
      • 2012-02-03
      • 1970-01-01
      • 2011-12-25
      相关资源
      最近更新 更多