【发布时间】:2017-08-13 07:17:37
【问题描述】:
我的 LoadingWindow 有问题。 我在 STA 模式下的新线程中启动一个新窗口。我知道这很不寻常,但对我来说是必需的。
问题是,在关闭窗口后 GC 并没有释放内存,并且窗口仍保留在可视活动树中:
我能做些什么来避免这种情况?
我的代码:
private void Button_Click(object sender, RoutedEventArgs e)
{
if (_window == null)
{
Thread thread = new Thread(ShowWindow);
thread.IsBackground = false;
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
}
else
{
_window.Dispatcher.Invoke(_window.Close);
_window = null;
}
}
private void ShowWindow()
{
_window = new Window();
_window.AllowsTransparency = true;
_window.Background = new SolidColorBrush(Color.FromArgb(70,0,0,0));
_window.Height = 1200D;
_window.Width = 1920D;
_window.WindowStartupLocation = WindowStartupLocation.Manual;
_window.Left = -1920D;
_window.Top = 0D;
_window.WindowStyle = WindowStyle.None;
_window.ShowDialog();
}
【问题讨论】:
-
为什么你试图在不同的线程上打开一个窗口?绝对不需要。如果要执行后台处理,请使用任务执行并根据需要更新表单。如果您不希望表单是模态的,请不要将其打开为模态
-
不幸的是这是必要的,因为主线程正在处理一些 ui 的东西(我们必须同步到服务器)并且需要 2-3 秒。需要加载屏幕来向用户显示客户端正在做某事。
-
不,不是。启动画面不适用于单独的线程,它们是出现在其他表单之上的无模式表单。过去(即在.NET 4.0 之前)人们使用BackgroundWorker。现在他们使用
async/await和任务。与服务器同步并不意味着您也需要阻止 UI 线程。发布您的代码。需要解决的问题是您对服务器的阻塞等待 -
你在说什么服务器,你如何与它通信?你现在是如何完成处理的? SOAP 代理、ADO.NET、WebClient 和 HttpClient 具有异步方法,因此您无需阻塞等待响应。任何其他通信方式都可以在后台运行
Task.Run -
您在应用程序中看到的启动屏幕或进度屏幕不适用于不同的线程。他们在 UI 线程本身上工作。虽然处理是在后台线程中执行的,或者使用异步技术进行
标签: wpf multithreading user-interface