【发布时间】: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