【问题标题】:Multithreading - window first closed, then created, even though in code the method for creation is called first多线程 - 首先关闭窗口,然后创建,即使在代码中首先调用创建方法
【发布时间】:2014-11-14 16:21:08
【问题描述】:

这是我执行的代码:

OpenMyWindowInNewThread(1280, 1024, 5);
//do some stuff
CloseMyWindow();

以下是方法:

public void OpenMyWindowInNewThread(int width, int height, int top)
    {
        thread = new Thread(x => OpenMyWindow(width, height, top));
        thread.IsBackground = true;
        thread.SetApartmentState(ApartmentState.STA);
        thread.Start();
    }

    public void CloseMyWindow()
    {
        if (myWindow != null)
        {
            myWindow.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Action)(() =>
            {
                myWindow.Close();
                myWindow = null;
            }));
        }
    }

private void OpenMyWindow(int width, int height, int top)
    {
        myWindow = new MyView();
        myWindow.Closed += new EventHandler(MyWindow_Closed);

        myWindow.Width = width;
        myWindow.Height = height;
        myWindow.Top = top;
        myWindow.Left = 0;

        myWindow.ShowDialog();
    }

当我第一次调用第一个代码时,屏幕会按原样显示并关闭。但是,当我第二次执行代码时,会发生以下情况:首先调用 OpenMyWindowInNewThread(),然后调用 OpenMyWindow(),然后是 CloseMyWindow() 方法中的 if 条件,然后调用 MyView() OpenMyWindow() 方法中的构造函数。因此,窗口永远不会关闭,因为它首先关闭,然后才创建。

为什么会这样?谁能解释一下?

【问题讨论】:

  • 您正在使用单独的线程来创建新窗口。该线程设置为后台优先级。不能保证它会在关闭调用之前执行。这是典型的比赛条件。使用手动重置事件并在关闭窗口中阻止,直到被触发
  • 不要创建多个 UI 线程。只是不要。为整个应用程序使用单个 UI 线程。尝试处理多个消息循环只会让自己陷入痛苦的世界。
  • 您的描述实际上没有意义。在构造函数返回 after 之前,不可能将 myWindow 设置为新的表单引用。所以CloseMyWindow() 在构造函数之前不能看到它是非空的。也就是说,正如其他人所指出的,是的,你确实在这里有一场比赛,是的,你应该在一个线程上完成所有的 UI。如果您想在其他处理正在进行时显示对话框,请在 UI 线程中显示对话框,并使用 BackgroundWorker 或其他辅助线程来执行其他处理(这可能不应该在主 UI 上完成反正线程!)
  • @Servy 那么您建议使用什么替代多线程?
  • @petko_stankoski 只需使用单个 UI 线程即可完成所有操作。如果您不希望它成为模态,请不要使表单成为模态。无论您想用 2 个 UI 线程做什么,几乎可以肯定只用 1 个就可以轻松得多。

标签: c# multithreading window


【解决方案1】:

问题是你有两个线程访问窗口;关闭窗口的线程在执行打开的线程完成其操作之前运行 close 方法。解决这个问题的最简单方法是锁定窗口的打开和关闭。如前所述,多个 UI 线程并不是一个简单的概念,而且会变得非常非常混乱!

private static object _syncLock = new object();

public void CloseMyWindow()
{
    lock(_syncLock)
    {
        if (myWindow != null)
        {
            myWindow.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Action)(() =>
            {
                myWindow.Close();
                myWindow = null;
            }));
        }
    }
}

private void OpenMyWindow(int width, int height, int top)
{
    lock(_syncLock)
    {
        myWindow = new MyView();
        myWindow.Closed += new EventHandler(MyWindow_Closed);

        myWindow.Width = width;
        myWindow.Height = height;
        myWindow.Top = top;
        myWindow.Left = 0;

        myWindow.ShowDialog();
    }
}

【讨论】:

    猜你喜欢
    • 2021-04-21
    • 2018-09-21
    • 2021-10-11
    • 2014-09-30
    • 1970-01-01
    • 1970-01-01
    • 2015-02-25
    • 1970-01-01
    • 2013-02-16
    相关资源
    最近更新 更多