【问题标题】:Threading issue - Window not updating/responding [duplicate]线程问题 - 窗口不更新/响应 [重复]
【发布时间】:2012-01-16 22:04:41
【问题描述】:

可能重复:
WPF and cross thread operations

我在我的 wpf 应用程序中显示一个窗口时遇到问题,但没有更新视图。将光标放在打开的窗口上时,会显示加载图标并且窗口无响应。我认为这可能是由于我没有足够经验看到的一些线程问题。


设置如下:

我的主程序在启动时运行,并创建一个实现自定义界面(IPlayer)的 MainWindow 窗口的实例。然后主程序运行一个与 IPlayer 交互的进程以完成某些任务,其想法是主程序从 MainWindow 请求操作,这会提示用户进行某种输入并显示结果。

为了清楚起见,我将简化代码。假设这个程序只是运行一种聊天机器人游戏。

class MainProgram
{

    [STAThread]
    static void main(string[] args)
    {
        MainWindow wdw = new MainWindw();
        Game g = new Game(wdw);

        wdw.Show();
        g.RunGame();
    }

}

class Game
{
    public IPlayer p;
    Game(IPlayer) { this.p = p; }

    public RunGame()
    {
        string r = GetResponse("How was your day?");

        ...
    }
}


public partial class Human_Player : Window, IPlayer
{
    public string GetResponse(string Question)
    {
        ShowQuestion(Question);
        string r = GetResponse();
        DisplayResponse(r);
        return r;
    }

    ...
}

我给在一个单独的线程中运行 RunGame() 一个这样的镜头:

Thread thread = new Thread(new ThreadStart(game.RunGame));
thread.Start(); 

但收到 InvalidOperationException 响应,指出“调用线程无法访问此对象,因为不同的线程拥有它。”

这里的任何帮助将不胜感激,因为我对这些东西很陌生。提前谢谢!


编辑:

澄清一下,我目前没有创建任何新线程。因此,我不认为我在做任何多线程。打开窗口后,我试图在主线程上运行 game.RunGame() 。 runGame 方法包含一个大循环,该循环调用 Human_Player 窗口上的一个方法来更改 UI。

据我所知只有两个线程: - 主线程 - MainProgram 和 Game 在这里运行。我认为窗户也在这里运行,但我可能是错的......请澄清 - 渲染线程 - 在这里渲染 UI。

【问题讨论】:

  • 一些 .NET 线程建议:仅在自己的线程上更新可视对象。你在一个单独的线程上搞乱 MainWindow 吗?
  • 多线程时,您不能直接从 UI 线程访问某些内容。哪个对象抛出此异常?
  • 实际上它现在的编写方式,我正在尝试从主线程做所有事情。我可能错了,但我认为这是可能的,因为 mainProgram 通过调用 wdw.Show() 启动窗口,然后通过调用 game.DoSomething() 继续执行。 game.DoSomething() 然后会在窗口内调用一个函数,该函数会更改 UI 并返回一些结果......我一定是在这里遗漏了一些东西......

标签: c# wpf multithreading user-interface


【解决方案1】:

啊,这个问题被问了很多次了...您不能从与控件关联的 Dispatcher 线程不同的线程更新 GUI 控件。您需要使用 Dispatcher.BeginInvoke 运行更新代码,以从正确的线程更新 GUI。

如果您没有从其他线程运行代码,那么您的方法可能执行时间过长,从而导致 GUI 挂起,因为事件线程被阻止接受用户输入。

【讨论】:

  • 能否解释 game.RunGame() 与 Human_Player 窗口在不同线程上的原因?
  • @marrithl2: 好的,如果你没有使用 Thread thread = new Thread(new ThreadStart(game.RunGame));那么它不在不同的线程上。也许您的方法执行时间过长,从而导致 GUI 挂起。试试用秒表看看。
  • 使用秒表,一切似乎都运行得很快。这些方法在 Human_Player 类上花费的时间不到一毫秒。 runGame 方法需要一段时间,因为它在两个玩家之间运行整个游戏,不断地在两个玩家之间调用方法。 (其实是战舰游戏)
  • 因此,如果 runGame 方法需要一段时间,则可能是 UI 挂起的原因。
  • 在 runGame 方法的循环中,攻击之间的时间只有 11 毫秒。这对我来说似乎并不多,但我不确定杀死渲染线程需要什么......本质上,runGame 方法是一个循环,它从每个玩家那里获取攻击并检查获胜者。
【解决方案2】:

听起来您的游戏代码正在循环运行并占用您所有 UI 的处理时间。听起来您并没有向调度员释放控制权。

您的游戏代码不应循环,它应该运行一次迭代,然后将控制权返回给调度程序。您需要创建一个计时器控件,改为定期调用您的游戏代码。

【讨论】:

  • 这是个好主意...我得研究一下
猜你喜欢
  • 2010-09-11
  • 2015-09-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-24
相关资源
最近更新 更多