//
// Copyright (c) 2002
// Ronald Kevin Burton
//
// Z poniższym kodem nie jest związana żadna gwarancja poprawności działania.
// Program został dołączony do książki ".NET CLR. Księga eksperta" w celu
// ilustracji koncepcji i zasad przedstawionych w tej książce. Program może być 
// używany na własne ryzyko.
//
// Przyznaje się prawo do użycia lub kopiowania tego oprogramowania do dowolnego celu
// bez konieczności ponoszenia żadnych opłat pod warunkiem, że powyższe uwagi zostaną 
// zachowane we wszystkich kopiach. Przyznaje się także prawo do modyfikacji kodu
// i dystrybucji zmodyfikowanego kodu pod warunkiem zachowania powyższych uwag
// oraz dołączenia informacji mówiącej o modyfikacji kodu.
//
//
using System;
using System.Threading;

namespace ProfilingSamples
{
	public class GCPinnedMain 
	{
		private ManualResetEvent asyncEvent;
		unsafe void PinnedThread()
		{
			byte [] ba1 = new byte[100];
			byte [] ba2 = new byte[100];
			byte [] ba3 = new byte[100];
			byte [] ba4 = new byte[100];
			for(int i = 0; i < ba1.Length; i++)
			{
				ba1[i] = (byte)(i % 256);
				ba2[i] = (byte)(i % 256);
				ba3[i] = (byte)(i % 256);
				ba4[i] = (byte)(i % 256);
			}
			fixed(byte *p1 = ba1,p2 = ba2, p3 = ba3, p4 = ba4)
			{
				asyncEvent.WaitOne();
			}
		}
		void TestThread()
		{
			Thread t;
			asyncEvent = new ManualResetEvent(false);
			try
			{
				while(true)
				{
					asyncEvent.Reset();
					t = new Thread(new ThreadStart(PinnedThread));
					t.Start();

					Thread.Sleep(500);

					// Wykonanie GC zmienia generację obiektu
					GC.Collect();

					asyncEvent.Set();
					t.Join();

					Thread.Sleep(500);
					// Wykonanie GC zmienia generację obiektu
					GC.Collect();

					Thread.Sleep(500);
				}
			}
			catch(Exception e)
			{
				Console.WriteLine("TestThread przerywa pracę: {0}", e.Message);
			}
		}
		static void Main(string [] args)
		{
			GCPinnedMain m = new GCPinnedMain();
			Thread testThread = new Thread(new ThreadStart(m.TestThread));
			testThread.Start();
			string input = Console.ReadLine();
			testThread.Abort();
			testThread.Join();
		}
	}
}