대용량의 메모리를 할당하는 컨트롤이 UI의 입력 이벤트를 사용하여 파괴되고 재구성되는 경우 문제가 발생했습니다.무거운 WPF 컨트롤에서 결정적으로 사용되는 메모리를 해제하는 방법은 무엇입니까?
분명히, Window의 Content를 null로 설정하는 것은 포함 된 Control이 사용하고있는 메모리를 해제하기에 충분하지 않습니다. 결국 GCed 될 것입니다. 그러나 컨트롤을 파괴하고 구성하는 입력 이벤트가 더 자주 발생함에 따라 GC는 일부 개체를 건너 뛴 것으로 보입니다.
나는이 예에 고장 :
XAML :
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525" x:Name="window" MouseMove="window_MouseMove">
</Window>
C 번호 :
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace WpfApplication1
{
public partial class MainWindow : Window
{
private class HeavyObject : UserControl
{
private byte[] x = new byte[750000000];
public HeavyObject()
{
for (int i = 0; i++ < 99999999;) { } // just so we can follow visually in Process Explorer
Content = "Peekaboo!"; // change Content to el cheapo re-trigger MouseMove
}
}
public MainWindow()
{
InitializeComponent();
//Works 1:
//while (true)
//{
// window.Content = null;
// window.Content = new HeavyObject();
//}
}
private void window_MouseMove(object sender, MouseEventArgs e)
{
if (window.Content == null)
{
GC.Collect();
GC.WaitForPendingFinalizers();
// Works 2:
//new HeavyObject();
//window.Content = "Peekaboo!"; // change Content to el cheapo re-trigger MouseMove
//return;
window.Content = new HeavyObject();
}
else
{
window.Content = null;
}
}
}
}
이 각 MouseMove 이벤트에서 ~의 750메가바이트 개체 (HeavyObject)을 할당 넣어 않습니다 그것은 메인 윈도우의 콘텐츠입니다. 커서가 창에서 계속 유지되면 내용 변경으로 끝없이 이벤트가 다시 트리거됩니다. 헤비 오브젝트에 대한 참조가 다음 구성 전에 무시되고 GC에 대한 쓸데없는 시도가 트리거됩니다.
ProcessExplorer/Taskman에서 볼 수있는 것은 가끔 1.5GB 이상이 할당된다는 것입니다. 그렇지 않다면, 마우스를 격렬히 움직여서 창을 닫고 다시 입력하십시오. LARGEADDRESSAWARE없이 x86 용으로 컴파일하면 대신 OutOfMemoryException이 발생합니다 (~ 1.3GB 제한).
HeavyObject를 마우스 입력 ("Works 1"섹션의 주석 처리 제거)을 사용하지 않고 무한 루프에 할당하거나 마우스 입력으로 할당을 트리거하지만 개체를 시각적 트리 (주석 2의 "주석 2").
그래서 시각적 트리를 지연시키는 리소스와 관련이 있다고 가정합니다. 그러나 또 다른 이상한 효과가 있습니다. 커서가 Window 외부에있을 때 1.5GB가 소비되면 MouseMove가 다시 트리거 될 때까지 GC가 시작되지 않는 것 같습니다. 적어도 메모리 소비는 더 이상의 이벤트가 발생하지 않는 한 안정화되는 것으로 보입니다. 그래서 활동이 없을 때 어딘가에 오래 살아있는 참조가 남아 있거나 GC가 게으르다.
나에게 이상하게 보입니다. 무슨 일이 일어나는지 알아낼 수 있니?
편집 : BalamBalam이 주석으로 달음 : 컨트롤을 파괴하기 전에 컨트롤 뒤에있는 데이터를 역 참조 할 수 있습니다. 그것은 계획 B 였을 것입니다. 그럼에도 불구하고 좀 더 일반적인 해결책이있을 수 있습니다.
그런 컨트롤을 말하는 것은 나쁜 코드는 도움이되지 않습니다. 내가 왜 dereferencing 후 몇 가지 틱에 대한 UI를 혼자두고 떠날 경우 GCed 얻을 개체 참조를 보유하고 싶습니다,하지만 영원히 주위에 (사용자 입력에 의해 만들어 지도록했습니다) 사용자 입력 즉시 걸립니다. 장소.
나는 당신의 문제가 무엇인지 알 수 없습니다. 여기에있는 미친 코드가 테스트 용일 뿐이라고 가정합니다. 그러나 당신은 한 가지를 배웠습니다. GC를 강요하려는 시도는 종종 자신이 생각하는대로하지 않습니다. –
코드는 문제가 발생하지 않는 두 가지 해결 방법을 포함하는 예제입니다. 단지 가정을 제한하기 위해서. 문제는 다음과 같습니다 : 창 콘텐트로 큰 콘트롤 -> 창 콘텐트로 새 콘트롤 설정 ** ** 마우스 입력으로 ** -> 한 번에 두 개 이상의 빅 컨트롤이 살아 있습니다. –
글쎄, 아무도 마우스 이동시 750MB의 오브젝트를 할당하지 않기를 바랍니다. 그것은 매우 비현실적인 시나리오입니다. 그래서 여러분의 전체 재단은 흔들립니다. –