「C#Developer」コースの将来の学生と興味のあるすべての人のために、私たちは有用な資料の翻訳を用意しました。
また、「すべてを実行するLINQメソッド」というトピックに関する公開ウェビナーに参加することをお勧めします。参加者は、LINQファミリーのテクノロジーの6つの代表、メインクエリ操作の3つのコンポーネント、遅延および即時実行、並列クエリについて説明します。
大規模な企業プロジェクトに携わったことのある人なら誰でも、メモリリークが大きなホテルのネズミのようなものであることを知っています。それらの数が少ないと気付かないかもしれませんが、繁殖したり、台所に忍び込んだり、周りのすべてを汚したりする場合に備えて、常に目を光らせておく必要があります。
, — . 8 , .NET , . , , . , .
.NET
« » . , (GC — garbage collector), ?
. — , , . , , , . , , event
.
, - ( ) . . .NET , . , , , , . Dispose
, ( ). .NET ., Marshal
PInvoke
( ).
:
1.
Debug | Windows | Show Diagnostic Tools, . -, , , Visual Studio, . . 2 : GC Pressure ( ).
, (Process Memory) :
, , , , - .
GC Pressure, :
GC Pressure — , . , , .
, , , . Visual Studio Enterprise , . .
2. , Process Explorer PerfMon
— (Task Manager) Process Explorer ( SysInternals). , . , , .
PerfMon , . , , . Process | Private Bytes.
, . , . , / , (). , GC Pressure. , , .
, , . , - ( ).
3.
-. . ( ), , .
.NET: dotMemory, SciTech Memory Profiler ANTS Memory Profiler. «» , Visual Studio Enterprise.
. . . . , :
, , GC Root.
GC Root — , , , GC Root, . , , GC Roots. « .NET».
— , . , . , :
- (Idle state) . - .
, .
, , . .
.
.
New-Created-Instances, , . «path to GC Root» , .
, SciTech , :
4. «Make Object ID»
5 , - C# .NET, , , Finalizer. , . Make Object ID (Immediate Window).
, , . , , . , , :
, .
, ,
Make Object ID
.Immediate $1
, ,Object ID
.
, .
.
GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect();
5. $1
. null
, , . , .
:
, :
, , .
: .NET Core 2.X (). , , . , , .
5.
, , . , .
:
(Events) .NET , . , , . , : 5 , - C# .NET,
, , , . , GC Roots, .
— . , OutOfMemory. .
WPF . — DependencyObject INotifyPropertyChanged. , WPF ( ViewModel) , . WPF StackOverflow.
. , , , — . :
public class MyClass
{
private int _wiFiChangesCounter = 0;
public MyClass(WiFiManager wiFiManager)
{
wiFiManager.WiFiSignalChanged += (s, e) => _wiFiChangesCounter++;
}
, . Live Stack GC Root. , , , . . , . :
public class MyClass
{
public MyClass(WiFiManager wiFiManager)
{
Timer timer = new Timer(HandleTick);
timer.Change(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(5));
}
private void HandleTick(object state)
{
// do something
}
8 .NET.
6. Dispose
.NET . .NET , Win32 API. , , , , , , .
.NET Framework
, , IDisposable
. , , Dispose
. — Dispose
. , using
.
public void Foo()
{
using (var stream = new FileStream(@"C:\Temp\SomeFile.txt",
FileMode.OpenOrCreate))
{
// do stuff
}// stream.Dispose() will be called even if an exception occurs
using
try / finally
, Dispose
finally
.
Dispose
, , .NET
Dispose. , Dispose
, Finalizer
, . , Finalizer
.
, Dispose
. :
public class MyClass : IDisposable
{
private IntPtr _bufferPtr;
public int BUFFER_SIZE = 1024 * 1024; // 1 MB
private bool _disposed = false;
public MyClass()
{
_bufferPtr = Marshal.AllocHGlobal(BUFFER_SIZE);
}
protected virtual void Dispose(bool disposing)
{
if (_disposed)
return;
if (disposing)
{
// Free any other managed objects here.
}
// Free any unmanaged objects here.
Marshal.FreeHGlobal(_bufferPtr);
_disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
~MyClass()
{
Dispose(false);
}
}
— . , ( Finalizer
), Dispose()
.
GC.SuppressFinalize(this)
. , Finalizer
, . Finalizer- . Finalizer
F-Reachable-Queue
, . .
7.
. , , . , - , . , , .
. :
Process currentProc = Process.GetCurrentProcess();
var bytesInUse = currentProc.PrivateMemorySize64;
PerformanceCounter
— , PerfMon
:
PerformanceCounter ctr1 = new PerformanceCounter("Process", "Private Bytes", Process.GetCurrentProcess().ProcessName);
PerformanceCounter ctr2 = new PerformanceCounter(".NET CLR Memory", "# Gen 0 Collections", Process.GetCurrentProcess().ProcessName);
PerformanceCounter ctr3 = new PerformanceCounter(".NET CLR Memory", "# Gen 1 Collections", Process.GetCurrentProcess().ProcessName);
PerformanceCounter ctr4 = new PerformanceCounter(".NET CLR Memory", "# Gen 2 Collections", Process.GetCurrentProcess().ProcessName);
PerformanceCounter ctr5 = new PerformanceCounter(".NET CLR Memory", "Gen 0 heap size", Process.GetCurrentProcess().ProcessName);
//...
Debug.WriteLine("ctr1 = " + ctr1 .NextValue());
Debug.WriteLine("ctr2 = " + ctr2 .NextValue());
Debug.WriteLine("ctr3 = " + ctr3 .NextValue());
Debug.WriteLine("ctr4 = " + ctr4 .NextValue());
Debug.WriteLine("ctr5 = " + ctr5 .NextValue());
perfMon, .
. CLR MD (Microsoft.Diagnostics.Runtime) . , , , . .
, CLR MD, DumpMiner .
, , , Application Insights.
8.
— . . , :
[Test]
void MemoryLeakTest()
{
var weakRef = new WeakReference(leakyObject)
// Ryn an operation with leakyObject
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
Assert.IsFalse(weakRef.IsAlive);
}
, .NET Memory Profiler SciTech dotMemory, API:
MemAssertion.NoInstances(typeof(MyLeakyClass));
MemAssertion.NoNewInstances(typeof(MyLeakyClass), lastSnapshot);
MemAssertion.MaxNewInstances(typeof(Bitmap), 10);
, , , , : .
, , . .
→ « C#».
→ « LINQ, ».