从线程启动时窗口未正确关闭

时间:2017-03-21 14:39:52

标签: wpf multithreading user-interface

我的LoadingWindow有问题。 我在STA模式的新线程中启动一个新窗口。我知道这很不寻常,但在我的情况下需要。

问题是,在关闭窗口后,GC不会释放ram,窗口仍保留在可视活动树中:

See image here

我该怎么做才能避免这种情况?

我的代码:

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();
}

3 个答案:

答案 0 :(得分:0)

您在应用程序上看到的启动画面不适用于不同的线程。它们是仍然在UI线程上运行的无模式窗体(使用Form.Show打开,而不是Form.ShowDialog)。任何后台工作都在后台线程上执行。对服务器的呼叫通常根本不使用线程。异步方法用于与Web服务,数据库等进行通信。

WCF服务代理始终生成异步方法。在.NET 4.0之前,方法遵循APM模式,即BeginMyMethod/EndMyMethod。从.NET 4.5.2开始,异步方法基于任务,即Task<SomeResult> MyMethodAsync()

鉴于新的异步方法,您的代码可以像这样简单:

private async void Button_Click(object sender, RoutedEventArgs e)
{
    using(var progForm =new MyProgressForm())
    {
        progForm.Text="Running";
        progForm.Show(this);
        using(var client = new myServiceClient())
        {
            await client.MyMethodAsync();
        }
        progForm.Close();
}

那就是它。用户界面不会阻止MyMethodAsync等待返回。 await之后的代码将仅在服务器完成后运行

可以使用TaskFactory.FromAsync方法将APM样式的方法转换为任务。在TPL and Traditional .NET Framework Asynchronous Programming

中更详细地讨论了将APM样式或基于事件的接口转换为任务

Task.FromAsync与公开AMP方法的代理一起使用,代码可能如下所示:

private async void Button_Click(object sender, RoutedEventArgs e)
{
    using(var progForm =new MyProgressForm())
    {
        progForm.Text="Running";
        progForm.Show(this);
        using(var client = new myServiceClient())
        {
            await Task.FromAsync(client.BeginMyMethod,client.EndMyMethod,null);
        }
        progForm.Close();
}

答案 1 :(得分:0)

我知道这不是一个很好的解决方案......实际上这很糟糕。但在我的情况下,不可能以另一种方式修复。但暂时修复是可以的。 要完成此操作:我以这种方式更改了代码:

spark.sql.execution.id

当我们的应用程序完全更改时,我首先删除它:D 感谢@Panagiotis Kanavos提供的积极反馈。 99%的情况下你的权利;) 但在我的情况下,我不能执行异步方法......将来我们可以但不是现在。

答案 2 :(得分:-1)

这是一个像这样的闪屏吗? splash on CBR