2010-12-05 129 views
1

我有一個WPF窗口,我用Window.Show()顯示。 當我點擊X時,表單關閉。 但它仍然在內存中,而且GC永遠不會清理它。 另外我沒有任何refrences /句柄。處理WPF窗口

確實有人知道什麼可能導致它留在內存中?

謝謝!

更新: 我使用下面的代碼來創建窗口:

Public Sub OpenPageWindow(ByVal nick As String) 
     Dim found As Boolean 

     For Each pw As PageWindow In Application.Current.Windows.OfType(Of PageWindow)() 
      If Not pw.Tag Is Nothing Then 
       If pw.Tag.ToString() = nick Then 
        If pw.IsVisible = False Then 
         pw.Show() 
        End If 
        Exit Sub 
       End If 
      End If 
     Next 

     If found = False Then 
      Dim p As New PageWindow With {.Name = "pw" & nick, .Tag = nick, _ 
              .Title = "Chatting with " & nick, .ShowActivated = False} 
      p.Show() 
     End If 
    End Sub 

和下面的代碼隱藏窗口本身:在XAML

Public Class PageWindow 
    Implements System.IDisposable 

    Public UserPressedExit As Boolean 
    Dim MainWin As MainWindow 

    Private _IsBuddy As Boolean 
    Private _IsBlocked As Boolean 
    Private _IsOnline As Boolean 

    Public Property FirstOpen As Boolean 

    Public Property IsOnline As Boolean 
     Get 
      Return _IsOnline 
     End Get 
     Set(ByVal value As Boolean) 
      If _IsOnline <> value Then 
       _IsOnline = value 
      End If 
     End Set 
    End Property 

    Public Property IsBuddy As Boolean 
     Get 
      Return _IsBuddy 
     End Get 
     Set(ByVal value As Boolean) 
      If _IsBuddy <> value Then 
       _IsBuddy = value 
       'If value Then 
       ' btnAddBuddy.IsEnabled = False 
       ' iDeleteBuddy.IsEnabled = True 
       'Else 
       ' btnAddBuddy.IsEnabled = True 
       ' iDeleteBuddy.IsEnabled = False 
       'End If 
      End If 
     End Set 
    End Property 

    Private Sub Window_Loaded(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) 
     Try 
      MainWin = CType(Application.Current.Windows(0), MainWindow) 
     Catch ex As Exception 
      txtChat.AppendText("ERROR: " & ex.Message.ToString() & Environment.NewLine) 
     End Try 
    End Sub 

    Private Sub Window_Closed(ByVal sender As System.Object, ByVal e As System.EventArgs) 
     Me.Dispose() 
    End Sub 

    Private Sub txtTitle_PreviewMouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Input.MouseButtonEventArgs) 
     Me.DragMove() 
    End Sub 

    Private Sub pbMin_PreviewMouseUp(ByVal sender As System.Object, ByVal e As System.Windows.Input.MouseButtonEventArgs) 
     WindowState = Windows.WindowState.Minimized 
    End Sub 

    Private Sub pbClose_PreviewMouseUp(ByVal sender As System.Object, ByVal e As System.Windows.Input.MouseButtonEventArgs) 
     UserPressedExit = True 
     txtChat.Clear() 
     Me.Close() 
    End Sub 

    Private Sub txtSend_KeyUp(ByVal sender As System.Object, ByVal e As System.Windows.Input.KeyEventArgs) 
     If e.Key = Key.Enter Then 
      btnSend_Click(Nothing, Nothing) 
     End If 
    End Sub 

    Private Sub btnSend_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) 
     If String.IsNullOrWhiteSpace(txtSend.Text) Then 
      MessageBox.Show("Empty Message.") 
      txtSend.Text = "" 
     Else 
      Send(txtSend.Text) 

      txtSend.Text = "" 
     End If 
    End Sub 

    Public Sub Page(ByVal message As String) 
     If String.IsNullOrEmpty(message) = False Then 
      If MainWin.Settings.ShowPageTimestamp Then 
       txtChat.AppendText(Me.Tag.ToString() & " (" & Format(Date.Now, "HH:mm:ss") & "): " & message & Environment.NewLine) 
      Else 
       txtChat.AppendText(Me.Tag.ToString() & ": " & message & Environment.NewLine) 
      End If 

      If Me.IsFocused = False Then 

      End If 
     End If 
    End Sub 

    Private Sub Send(ByVal text As String) 
     'work on 389 event 
     MainWin.Send("PAGE " + Me.Tag.ToString + " " + text) 

     If MainWin.Settings.ShowPageTimestamp Then 
      txtChat.AppendText(MainWin.Settings.Nick & ": " & text & Environment.NewLine) 
     Else 
      txtChat.AppendText(MainWin.Settings.Nick & " (" & Format(Date.Now, "HH:mm:ss") & "): " & text & Environment.NewLine) 
     End If 
    End Sub 

#Region "IDisposable Support" 
    Private disposed As Boolean ' To detect redundant calls 

    ' This code added by Visual Basic to correctly implement the disposable pattern. 
    Public Sub Dispose() Implements IDisposable.Dispose 
     ' Do not change this code. Put cleanup code in Dispose(ByVal disposing As Boolean) above. 
     Dispose(True) 
     GC.SuppressFinalize(Me) 
    End Sub 

    Protected Overridable Sub Dispose(ByVal disposing As Boolean) 
     If Not Me.disposed Then 
      If disposing Then 
       'dispose managed state (managed objects). 
       RemoveHandler Me.Loaded, AddressOf Window_Loaded 
       RemoveHandler txtTitle.PreviewMouseDown, AddressOf txtTitle_PreviewMouseDown 
       RemoveHandler pbMin.PreviewMouseUp, AddressOf pbMin_PreviewMouseUp 
       RemoveHandler pbClose.PreviewMouseUp, AddressOf pbClose_PreviewMouseUp 
       RemoveHandler txtSend.KeyUp, AddressOf txtSend_KeyUp 
       RemoveHandler btnSend.Click, AddressOf btnSend_Click 
       RemoveHandler Me.Closed, AddressOf Window_Closed 

       BindingOperations.ClearBinding(txtTitle, TextBlock.TextProperty) 

       Me.Icon = Nothing 
       ibBackground = Nothing 
       'iDeleteBuddy = Nothing 
       'btnAddBuddy = Nothing 
       'iBlockUser = Nothing 
       pbMin = Nothing 
       pbClose = Nothing 
       MainWin = Nothing 

       Me.Resources.Clear() 

       GC.Collect() 
      End If 
     End If 
     Me.disposed = True 
    End Sub 

    Protected Overrides Sub Finalize() 
     ' Do not change this code. Put cleanup code in Dispose(ByVal disposing As Boolean) above. 
     Dispose(False) 
     MyBase.Finalize() 
    End Sub 
#End Region 
End Class 

然後將以下代碼:

<Window x:Class="PageWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="PageWindow" Height="300" Width="400" 
     Icon="Images\R2.ico" WindowStyle="None" ResizeMode="NoResize" 
     WindowStartupLocation="Manual" Loaded="Window_Loaded" 
     BorderThickness="2" BorderBrush="#FFAE28" 
     Closed="Window_Closed"> 
    <Window.Resources> 
     <Style x:Key="sRenegadeButton" TargetType="Button"> 
      <Setter Property="FontFamily" Value="Franklin Gothic Medium" /> 
      <Setter Property="FontSize" Value="12px" /> 
      <Setter Property="FontWeight" Value="Bold" /> 
      <Setter Property="Background" Value="Transparent" /> 
      <Setter Property="Foreground" Value="#FFAE28" /> 
      <Setter Property="Template"> 
       <Setter.Value> 
        <ControlTemplate TargetType="Button"> 
         <Border Name="Border" BorderBrush="#FFAE28" BorderThickness="1" CornerRadius="3" 
           Background="{TemplateBinding Background}" SnapsToDevicePixels="True"> 
          <Border Name="innerborder" BorderBrush="#FFAE28" BorderThickness="1" CornerRadius="3" 
            Background="{TemplateBinding Background}" SnapsToDevicePixels="True" Margin="1"> 
           <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" Name="content" /> 
          </Border> 
         </Border> 
         <ControlTemplate.Triggers> 
          <Trigger Property="IsMouseOver" Value="True"> 
           <Setter TargetName="Border" Property="BorderBrush" Value="#FFD528" /> 
           <Setter TargetName="innerborder" Property="BorderBrush" Value="#FFD528" /> 
           <Setter Property="Background" Value="#28FFAE28" /> 
           <Setter Property="Foreground" Value="#FFD528" /> 
          </Trigger> 
          <Trigger Property="IsPressed" Value="True"> 
           <Setter Property="Background" Value="#28FFAE28" /> 
           <Setter TargetName="content" Property="RenderTransform" > 
            <Setter.Value> 
             <TranslateTransform Y="1.0" /> 
            </Setter.Value> 
           </Setter> 
          </Trigger> 
          <Trigger Property="IsEnabled" Value="False"> 
           <Setter TargetName="Border" Property="BorderBrush" Value="#80E6A023" /> 
           <Setter TargetName="innerborder" Property="BorderBrush" Value="#80E6A023" /> 
           <Setter Property="Foreground" Value="#8CFFD528" /> 
          </Trigger> 
         </ControlTemplate.Triggers> 
        </ControlTemplate> 
       </Setter.Value> 
      </Setter> 
     </Style> 

     <Style x:Key="sRenegadeTextBox" TargetType="TextBox"> 
      <Setter Property="FontFamily" Value="Franklin Gothic Medium" /> 
      <Setter Property="FontSize" Value="12px" /> 
      <Setter Property="Foreground" Value="#FFD528" /> 
      <Setter Property="Background" Value="#28FFAE28" /> 
      <Setter Property="BorderBrush" Value="#FFAE28" /> 
      <Setter Property="CaretBrush" Value="#FFAE28" /> 
      <Setter Property="SelectionBrush" Value="#FFD528" /> 
      <Setter Property="BorderThickness" Value="1" /> 
      <Setter Property="Template"> 
       <Setter.Value> 
        <ControlTemplate TargetType="TextBox"> 
         <Border Name="Bd" BorderThickness="{TemplateBinding BorderThickness}" 
           BorderBrush="{TemplateBinding BorderBrush}" 
           Background="{TemplateBinding Background}" SnapsToDevicePixels="true"> 
          <ScrollViewer Name="PART_ContentHost" Background="{TemplateBinding Background}" 
              SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" /> 
         </Border> 
         <ControlTemplate.Triggers> 
          <Trigger Property="IsEnabled" Value="False"> 
           <Setter Property="Foreground" Value="#8CFFD528" /> 
           <Setter Property="Background" Value="#1EFFAE28" /> 
           <Setter Property="BorderBrush" Value="#80E6A023" /> 
           <Setter TargetName="PART_ContentHost" Property="Background" Value="#1EFFAE28"/> 
          </Trigger> 
         </ControlTemplate.Triggers> 
        </ControlTemplate> 
       </Setter.Value> 
      </Setter> 
     </Style> 
    </Window.Resources> 
    <Grid> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="21" /> 
      <RowDefinition Height="32" /> 
      <RowDefinition Height="*" /> 
      <RowDefinition Height="27" /> 
     </Grid.RowDefinitions> 

     <Grid.Background> 
      <ImageBrush x:Name="ibBackground" ImageSource="Images\page_back.gif" /> 
     </Grid.Background> 

     <Border Grid.Row="0" BorderBrush="#FFAE28" BorderThickness="0,0,0,2" 
       SnapsToDevicePixels="True" /> 

     <Grid Name="gTitleBar" Grid.Row="0" Background="#32FFAE28"> 
      <Grid.ColumnDefinitions> 
       <ColumnDefinition Width="*" /> 
       <ColumnDefinition Width="30" /> 
       <ColumnDefinition Width="32" /> 
      </Grid.ColumnDefinitions> 

      <TextBlock Name="txtTitle" Grid.Column="0" Text="{Binding Title,RelativeSource={RelativeSource FindAncestor,AncestorType=Window}}" 
         HorizontalAlignment="Stretch" VerticalAlignment="Center" 
         TextAlignment="Left" Margin="4,0,1,0" 
         PreviewMouseDown="txtTitle_PreviewMouseDown" 
         Foreground="#FED528" FontFamily="Franklin Gothic Medium" /> 

      <Image Name="pbMin" Grid.Column="1" Width="28" Height="15" 
        HorizontalAlignment="Center" VerticalAlignment="Center" 
        PreviewMouseUp="pbMin_PreviewMouseUp" Stretch="None"> 
       <Image.Style> 
        <Style TargetType="{x:Type Image}"> 
         <Setter Property="Source" Value="Images\min.png" /> 

         <Style.Triggers> 
          <Trigger Property="IsMouseOver" Value="True"> 
           <Setter Property="Source" Value="Images\min_o.png" /> 
          </Trigger> 
         </Style.Triggers> 
        </Style> 
       </Image.Style> 
      </Image> 
      <Image Name="pbClose" Grid.Column="2" Width="28" Height="15" 
        HorizontalAlignment="Left" VerticalAlignment="Center" 
        PreviewMouseUp="pbClose_PreviewMouseUp" Stretch="None"> 
       <Image.Style> 
        <Style TargetType="{x:Type Image}"> 
         <Setter Property="Source" Value="Images\close2.png" /> 

         <Style.Triggers> 
          <Trigger Property="IsMouseOver" Value="True"> 
           <Setter Property="Source" Value="Images\close2_o.png" /> 
          </Trigger> 
         </Style.Triggers> 
        </Style> 
       </Image.Style> 
      </Image> 
     </Grid> 

     <Grid Grid.Row="1"> 
      <Grid.ColumnDefinitions> 
       <ColumnDefinition Width="*" /> 
       <ColumnDefinition Width="25" /> 
       <ColumnDefinition Width="25" /> 
       <ColumnDefinition Width="25" /> 
       <ColumnDefinition Width="*" /> 
      </Grid.ColumnDefinitions> 

      <!--<Button Name="btnAddBuddy" Grid.Column="1" Margin="0,2,0,0"> 
       <Button.Style> 
        <Style TargetType="{x:Type Button}"> 
         <Setter Property="Background" Value="Transparent" /> 
         <Setter Property="Template"> 
          <Setter.Value> 
           <ControlTemplate TargetType="{x:Type Button}"> 
            <Grid> 
             <Border Name="Border" BorderBrush="Transparent" BorderThickness="1" CornerRadius="3" 
              Background="{TemplateBinding Background}" SnapsToDevicePixels="True"> 

             </Border> 
             <Image Name="iAddBuddy" Margin="1" Source="Images\Add Buddy 32x36.png" /> 
             <Image Name="iAddBuddyDissabled" Margin="1" Source="Images\Add Buddy 32x36.png" Visibility="Hidden" /> 
            </Grid> 

            <ControlTemplate.Triggers> 
             <Trigger Property="IsMouseOver" Value="True"> 
              <Setter TargetName="Border" Property="BorderBrush" Value="#FFD528" /> 
             </Trigger> 
             <Trigger Property="IsPressed" Value="True"> 
              <Setter Property="Background" Value="#FFD528" /> 
             </Trigger> 
             <Trigger Property="IsEnabled" Value="False"> 
              <Setter TargetName="Border" Property="BorderBrush" Value="Transparent" /> 
              <Setter TargetName="iAddBuddy" Property="Visibility" Value="Hidden" /> 
              <Setter TargetName="iAddBuddyDissabled" Property="Visibility" Value="Visible" /> 
             </Trigger> 
            </ControlTemplate.Triggers> 
           </ControlTemplate> 
          </Setter.Value> 
         </Setter> 
        </Style> 
       </Button.Style> 
      </Button> 

      <Border Name="bDeleteBuddyBorder" Grid.Column="2" BorderThickness="1" 
        SnapsToDevicePixels="True" Margin="0,2,0,0"> 
       <Image Name="iDeleteBuddy" Margin="1" IsEnabled="True" 
        Source="Images\Delete 32x32.png"> 
        <Image.Style> 
         <Style TargetType="{x:Type Image}"> 
          <Style.Triggers> 
           <Trigger Property="IsEnabled" Value="False"> 
            <Setter Property="Source" Value="Images\Delete Disabled 32x32.png" /> 
           </Trigger> 
          </Style.Triggers> 
         </Style> 
        </Image.Style> 
       </Image> 
       <Border.Style> 
        <Style TargetType="Border"> 
         <Setter Property="BorderBrush" Value="Transparent" /> 
         <Setter Property="Background" Value="Transparent" /> 
         <Style.Triggers> 
          <Trigger Property="IsMouseOver" Value="True"> 
           <Setter Property="BorderBrush" Value="#FFD528" /> 
          </Trigger> 
         </Style.Triggers> 
        </Style> 
       </Border.Style> 
      </Border> 

      <Border Name="bBlockUserBorder" Grid.Column="3" BorderThickness="1" 
        SnapsToDevicePixels="True" Margin="0,2,0,0"> 
       <Image Name="iBlockUser" Margin="1" IsEnabled="True" 
         Source="Images\Block Buddy 32x36.png"> 
        <Image.Style> 
         <Style TargetType="{x:Type Image}"> 
          <Style.Triggers> 
           <Trigger Property="IsEnabled" Value="False"> 
            <Setter Property="Source" Value="Images\Block Buddy Dissabled 32x36.png" /> 
           </Trigger> 
          </Style.Triggers> 
         </Style> 
        </Image.Style> 
       </Image> 
       <Border.Style> 
        <Style TargetType="Border"> 
         <Setter Property="BorderBrush" Value="Transparent" /> 
         <Setter Property="Background" Value="Transparent" /> 
         <Style.Triggers> 
          <Trigger Property="IsMouseOver" Value="True"> 
           <Setter Property="BorderBrush" Value="#FFD528" /> 
          </Trigger> 
         </Style.Triggers> 
        </Style> 
       </Border.Style> 
      </Border>--> 
     </Grid> 

     <TextBox Name="txtChat" Grid.Row="2" Margin="4,2,4,2" 
       Style="{StaticResource sRenegadeTextBox}" UndoLimit="0" /> 

     <Grid Grid.Row="3"> 
      <Grid.ColumnDefinitions> 
       <ColumnDefinition Width="*" /> 
       <ColumnDefinition Width="45" /> 
      </Grid.ColumnDefinitions> 

      <TextBox Name="txtSend" Grid.Column="0" MaxLength="495" 
        Height="22" Margin="4,1,2,4" VerticalContentAlignment="Center" 
        Style="{StaticResource sRenegadeTextBox}" UndoLimit="0" 
        KeyUp="txtSend_KeyUp" /> 
      <Button Name="btnSend" Content="Send" Grid.Column="1" 
        Style="{StaticResource sRenegadeButton}" 
        Height="22" Width="40" Margin="0,1,4,4" Click="btnSend_Click" /> 
     </Grid> 
    </Grid> 
</Window> 

基本上即使我創建一個空的WPF窗口wi主窗格和2個事件處理程序的背景圖像打開和關閉它仍然保留在內存中,但是當所有'空wpf'窗口關閉時,內存只會減少一點。只是一點點。爲什麼沒有完全處理簡單的窗口?我甚至嘗試實現上面編碼的處置功能。

+0

你怎麼知道它仍然在內存中? – svick 2010-12-05 13:03:06

+0

我點擊一個做windowname.show()的按鈕,然後在窗口中點擊X按鈕。並且內存在任務管理器中永遠不會改變。它爲每一個窗戶做出這樣的事情。 – tcables 2010-12-05 19:52:06

回答

1

的內存,如果你正在泄漏的句柄什麼是重要的 - 過程中(在任務管理器)中添加列GDI對象和把手。

當你打開和關閉你的窗口時,它會增加和減少 - 如果不是你有泄漏 - 泄漏來了一些記憶。 我會擔心一些kb不會馬上消失,他們最終會被清除或重用,但處理必須消失,所以他們可以是一個很好的指示。

當使用靜態事件處理程序或其他靜態結構時,通常會出現泄漏,這些結構持有對控件或窗口的引用 - 即靜態字典或散列表。如果需要引用,請記住在關閉時清理它或使用WeakReference。

配置方法只有在你的窗口/類有資源作爲成員變量時才需要,它必須正確實現(你的看起來是正確的 - 但不是必須的) - 你還必須確保Dispose()是實際上叫...

0

確實有人知道什麼可能導致它留在內存中?

您的窗口是否聽任何外部事件?如果是這樣,使用弱事件管理器可能會解決您的問題:http://msdn.microsoft.com/en-us/library/aa970850.aspx

+0

來自其他窗口的外部事件?沒有。 – tcables 2010-12-05 19:53:23

+0

它有自己的形式相關的事件..但我使用每一個刪除處理程序,但窗口不會處置。 – tcables 2010-12-13 18:07:11

0

您是否確定運行時確保在這種情況下執行垃圾回收?

我認爲GC很可能在這種情況下看不到需要執行垃圾回收。確保在你的代碼中調用GC.Collect,看看這是否改變了事情。

+0

在我提供的代碼中,我在Protected Overridable Sub Dispose(ByVal disposing As Boolean)中有GC.Collect。 – tcables 2010-12-10 21:11:29

2

首先,通過使用真正的內存工具(如redgate的內存分析器,它有一個免費試用版(http:// www。),確保你的內存問題是你認爲它的內存問題。 red-gate.com/products/ants_memory_profiler/)。

然後,如果您仍然遇到問題,分析器將突出顯示什麼是告訴GC不要清除它(由其他對象等引用)。

從一個快速的猜測,我會說它可能是你已經連線的事件處理程序,嘗試一旦它們完成後取消訂閱它們。

而且,與其他地方一樣說,叫GC.Collect作爲進一步的檢查