SORU
10 ŞUBAT 2011, PERŞEMBE


Neden bir Sistem yok.Zamanlayıcılar.Zamanlayıcı GC ama Sistem hayatta.İş parçacığı.Timer?

System.Timers.Timer örnekleri bir mekanizma tarafından canlı tutulur, görünür, ama System.Threading.Timer örneklerini değildir.

Örnek program, bir dönemsel ile System.Threading.Timer otomatik sıfırlama System.Timers.Timer:

class Program
{
  static void Main(string[] args)
  {
    var timer1 = new System.Threading.Timer(
      _ => Console.WriteLine("Stayin alive (1)..."),
      null,
      0,
      400);

    var timer2 = new System.Timers.Timer
    {
      Interval = 400,
      AutoReset = true
    };
    timer2.Elapsed  = (_, __) => Console.WriteLine("Stayin alive (2)...");
    timer2.Enabled = true;

    System.Threading.Thread.Sleep(2000);

    Console.WriteLine("Invoking GC.Collect...");
    GC.Collect();

    Console.ReadKey();
  }
}

Bu program çalıştırdığımda (.NET 4.0 Client, Sürüm, hata ayıklayıcısını dışında), System.Threading.Timer GC edildi

Stayin alive (1)...
Stayin alive (1)...
Stayin alive (2)...
Stayin alive (1)...
Stayin alive (2)...
Stayin alive (1)...
Stayin alive (2)...
Stayin alive (1)...
Stayin alive (2)...
Invoking GC.Collect...
Stayin alive (2)...
Stayin alive (2)...
Stayin alive (2)...
Stayin alive (2)...
Stayin alive (2)...
Stayin alive (2)...
Stayin alive (2)...
Stayin alive (2)...
Stayin alive (2)...

EDİT: Aşağıda John cevabı kabul ediyorum, ama bunu biraz açıklamak istedim.

Yukarıdaki örnek program (Sleep bir kesme noktası ile çalışırken, burada söz konusu nesnelerin durumunu ve GCHandle tablo:

!dso
OS Thread Id: 0x838 (2104)
ESP/REG  Object   Name
0012F03C 00c2bee4 System.Object[]    (System.String[])
0012F040 00c2bfb0 System.Timers.Timer
0012F17C 00c2bee4 System.Object[]    (System.String[])
0012F184 00c2c034 System.Threading.Timer
0012F3A8 00c2bf30 System.Threading.TimerCallback
0012F3AC 00c2c008 System.Timers.ElapsedEventHandler
0012F3BC 00c2bfb0 System.Timers.Timer
0012F3C0 00c2bfb0 System.Timers.Timer
0012F3C4 00c2bfb0 System.Timers.Timer
0012F3C8 00c2bf50 System.Threading.Timer
0012F3CC 00c2bfb0 System.Timers.Timer
0012F3D0 00c2bfb0 System.Timers.Timer
0012F3D4 00c2bf50 System.Threading.Timer
0012F3D8 00c2bee4 System.Object[]    (System.String[])
0012F4C4 00c2bee4 System.Object[]    (System.String[])
0012F66C 00c2bee4 System.Object[]    (System.String[])
0012F6A0 00c2bee4 System.Object[]    (System.String[])

!gcroot -nostacks 00c2bf50

!gcroot -nostacks 00c2c034
DOMAIN(0015DC38):HANDLE(Strong):9911c0:Root:  00c2c05c(System.Threading._TimerCallback)->
  00c2bfe8(System.Threading.TimerCallback)->
  00c2bfb0(System.Timers.Timer)->
  00c2c034(System.Threading.Timer)

!gchandles
GC Handle Statistics:
Strong Handles:       22
Pinned Handles:       5
Async Pinned Handles: 0
Ref Count Handles:    0
Weak Long Handles:    0
Weak Short Handles:   0
Other Handles:        0
Statistics:
      MT    Count    TotalSize Class Name
7aa132b4        1           12 System.Diagnostics.TraceListenerCollection
79b9f720        1           12 System.Object
79ba1c50        1           28 System.SharedStatics
79ba37a8        1           36 System.Security.PermissionSet
79baa940        2           40 System.Threading._TimerCallback
79b9ff20        1           84 System.ExecutionEngineException
79b9fed4        1           84 System.StackOverflowException
79b9fe88        1           84 System.OutOfMemoryException
79b9fd44        1           84 System.Exception
7aa131b0        2           96 System.Diagnostics.DefaultTraceListener
79ba1000        1          112 System.AppDomain
79ba0104        3          144 System.Threading.Thread
79b9ff6c        2          168 System.Threading.ThreadAbortException
79b56d60        9        17128 System.Object[]
Total 27 objects

John onun cevabı da belirttiği gibi, her iki zamanlayıcılar GCHandle tabloda onların geri arama (System.Threading._TimerCallback) kayıt. Hans zleri belirttiği gibi, state parametre de bu yapıldığında canlı tutulur.

John işaret etti, sebebi System.Timers.Timer hayatta olduğu için başvurulan tarafından geri (geçerken state parametre için iç System.Threading.Timer); aynı şekilde, bizim neden System.Threading.Timer GC edildi çünküdeğilonun geri tarafından başvurulan.

Açık bir başvuru 22 **'s geri arama (örneğin, Console.WriteLine("Stayin alive (" timer1.GetType().FullName ")")) GC önlemek için yeterlidir. ekleme

System.Threading.Timer tek-parametre kurucu kullanarak da zamanlayıcı state parametre olarak kendisine referans olacak, çünkü çalışır. Aşağıdaki kodu GCHandle tablodan geri tarafından başvurulan her bir yana hayatta hem zamanlayıcılar GC sonra tutar:

class Program
{
  static void Main(string[] args)
  {
    System.Threading.Timer timer1 = null;
    timer1 = new System.Threading.Timer(_ => Console.WriteLine("Stayin alive (1)..."));
    timer1.Change(0, 400);

    var timer2 = new System.Timers.Timer
    {
      Interval = 400,
      AutoReset = true
    };
    timer2.Elapsed  = (_, __) => Console.WriteLine("Stayin alive (2)...");
    timer2.Enabled = true;

    System.Threading.Thread.Sleep(2000);

    Console.WriteLine("Invoking GC.Collect...");
    GC.Collect();

    Console.ReadKey();
  }
}

CEVAP
13 ŞUBAT 2011, Pazar


Bu windbg ve sos, ve !gcroot ile benzer sorulara cevap verebilirsiniz

0:008> !gcroot -nostacks 0000000002354160
DOMAIN(00000000002FE6A0):HANDLE(Strong):241320:Root:00000000023541a8(System.Thre
ading._TimerCallback)->
00000000023540c8(System.Threading.TimerCallback)->
0000000002354050(System.Timers.Timer)->
0000000002354160(System.Threading.Timer)
0:008>

Her iki durumda da, yerel zamanlayıcı geri arama nesnesi (bir GCHandle) GC önlemek için vardır. Fark System.Timers.Timer Bu durumda geri arama System.Timers.Timer nesne içten System.Threading.Timer hayata kullanarak) başvuruyor

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • boniver

    boniver

    17 NİSAN 2006
  • DroidModderX ROOT Master

    DroidModderX

    14 ŞUBAT 2011
  • Nick Pitera

    Nick Pitera

    8 NİSAN 2006