Idisposable | Engin Polat\'ın Windows 8 , Windows Phone 8 ve C# içerikli programcılık sitesi

Arşiv

Etiketlenen yazılar idisposable

C# ile uzun süren method’ları kontrol altına alın

18 October 2013 Yorum yapılmamış

Uygulama geliştirirken karşılaştığımız birçok senaryoda çağırdığımız bir method’un uzun sürede cevap üretmemesinden dolayı kaynaklarımızı tükettiğini görebiliriz.

Çağırılan method’un belli bir zaman aşımı süresine sahip olması ve bu süre sonuna kadar değer üretmediyse sonlanması için birçok yöntem kullanabiliriz, fakat ben System.Threading namespace‘inde yeralan CancellationTokenSource sınıfını kullanan aşağıdaki yöntemi tercih ediyorum;

/// <summary>
/// Timeout süresinde tamamlanmayan method'u otomatik sonlandırır
/// </summary>
/// <param name="action">Çağırılacak method</param>
/// <param name="timeout">Milisaniye cinsinden zamanaşımı süresi</param>
/// <returns></returns>
public static bool Execute(Action action, int timeout)
{
	var tokenSource = new CancellationTokenSource();

	var token = tokenSource.Token;

	var task = Task.Factory.StartNew(action, token);

	if (!task.Wait(timeout, token))
	{
		tokenSource.Cancel();

		return false;
	}

	task.Dispose();

	return true;
}

/// <summary>
/// Timeout süresinde tamamlanmayan method'u otomatik sonlandırır
/// </summary>
/// <param name="action">Çağırılacak method</param>
/// <param name="timeout">Milisaniye cinsinden zamanaşımı süresi</param>
/// <returns></returns>
public static Tuple<bool, T> Execute<T>(Func<T> action, int timeout)
{
	var result = Tuple.Create(false, default(T));

	var tokenSource = new CancellationTokenSource();

	var token = tokenSource.Token;

	var task = Task.Factory.StartNew(() => { result = Tuple.Create(true, action.Invoke()); }, token);

	if (!task.Wait(timeout, token))
	{
		tokenSource.Cancel();
	}

	task.Dispose();

	return result;
}

Böylece değer döndürmeyen method’lar eğer timeout‘a uğramışsa geriye bool tipinde false değeri, timeout‘a uğramamışsa true değeri döndürebiliyoruz.

Geriye değer döndürecek method’lar eğer timeout‘a uğramışsa geriye Tuple sınıfından yeni bir değer döndürüyoruz. İki property’li Tuple‘ın birinci property’si timeout olup/olmadığını belirten bool tipinde, ikinci property ise çağırılan method’dan dönecek cevabın tipinin varsayılan değeri.

Bu methodlar sayesinde hatalar veya uzun süren method’ların kaynaklarımızı tüketmesi sorunları ile uğraşmadan uygulamalarımızı geliştirebiliriz.

Örnek kullanımlar;

Geriye değer döndürmeyen method’ları aşağıdaki örnek kullanım ile çağırabiliriz

var result = Execute(LongRunningProcess, 3000);

Geriye değer döndüren method’ları (örneğin int) aşağıdaki örnek kullanım ile çağırabiliriz

var result = Execute<int>(LongRunningProcess, 5000);

C# ile Geçici Dosya (Temporary File) oluşturma sınıfı yazalım

13 July 2011 Yorum yapılmamış

Projelerimizde dosya sistemi üzerinde geçici olarak dosya oluşturma ve işimiz bittiğinde silme ihtiyacı hissedebiliriz.

Bu yazıyı okumadan önce Hem benzersiz hem de geçici dosya oluşturmanın en kolay yolu ve C# ile Geçici Dosya Oluşturmak başlıklı yazılarımı okumanızı öneririm.

Bu linkte bulduğum yöntemi çok kullanışlı buldum ve sizler (aynı zamanda kendim) için türkçeleştirdim;

public class TempFile : IDisposable
{
	public TempFile() : this(string.Empty)
	{ }

	private readonly string _tmpfile;

	public TempFile(string extension)
	{
		_tmpfile = Path.GetTempFileName();

		if (!string.IsNullOrEmpty(extension))
		{
			string newTmpFile = _tmpfile + extension;

			/// Yeni bir geçici dosya oluşturulur
			File.Create(newTmpFile, 0);
			/// Eski geçici dosya silinmediyse, silinir.
			File.Delete(_tmpfile);

			/// Yeni oluşturulan geçici dosya kullanıma hazır!
			_tmpfile = newTmpFile;
		}
	}

	public string FullPath
	{
		get { return _tmpfile; }
	}

	void IDisposable.Dispose()
	{
		if (!string.IsNullOrEmpty(_tmpfile) && File.Exists(_tmpfile))
		{
			File.Delete(_tmpfile);
		}
	}
}

Kullanımına örnek;

using(TempFile tmp = new TempFile(".dat")) /// dat uzantılı bir geçici dosya oluşturuluyor
{
	/// FullPath özelliğinden geçici dosyanın yolu ve dosya adı alınabilir;
	string filename = tmp.FullPath;
}

C# İsimsiz Tipler – Anonymous Types

21 January 2010 2 yorum

Sadece bir method içerisinde kullanacağınız basit class‘lara kaç defa ihtiyaç duydunuz? Böyle bir class’a her ihtiyaç duyduğunuzda yapmanız gereken, yeni bir class oluşturup, bütün tanımlama kodlarını (private alanlar, public alanlar, vs.) yazmaktır.

C# dili, İsimsiz Tip (Anonymous Type) tanımlamaya izin veriyor. Üstelik, private ve public öğelerin oluşturulmasını ve yönetilmesini C# dilinin kendisi üstleniyor.

public class HataLogla()
{
	var Hata = new { Mesaj = "Hata Mesajının Kendisi", Tarih = DateTime.Now, Yer = "XClass.YMethod" };
	var Kullanici = new { Id = 42, AdSoyad = "Engin Polat", Yonetici = "Ali Veli" };

	string Loglanacak = string.Format("Hata Mesajı: {0}\nTarih: {1} {2}\nHatanın Oluştuğu Yer: {3}\n\nKullanıcıId: {4}\nKullanıcı Adı: {5}\nYöneticisi: {6}", Hata.Mesaj, Hata.ToShortDateString(), Hata.Tarih.ToLongTimeString(), Hata.Yer, Kullanici.Id, Kullanici.AdSoyad, Kullanici.Yonetici);

	File.WriteAllText(Loglanacak, @"C:\Log\Log.txt");

	MessageBox.Show(Hata.Mesaj, Hata.Tarih);
}

Yukarıdaki kodda yer alan Hata ve Kullanici değişkenlerinin tipleri, derleme zamanında derleyici tarafından otomatik oluşturulur. Eğer method‘un içerisine aşağıdaki kodları eklersek;

MessageBox.Show("Hata değişkeninin tipi : " + Hata.GetType().ToString());
MessageBox.Show("Kullanici değişkeninin tipi : " + Kullanici.GetType().ToString());

Mesaj kutularında şu değerleri görürüz;

Hata değişkeninin tipi : <>f_AnonymousType0’3[System.String,System.DateTime,System.String]
Kullanici değişkeninin tipi : <>f_AnonymousType0’3[System.Int32,System.String,System.String]

Farkettiğiniz gibi, böyle bir tip oluşturmaya çalışırsak, derleme zamanında hata alırız, ama C# derleyicisi bizim için bu tipleri oluşturuyor.

Değişkenin tipini veremeyeceğimiz için, C# diline var anahtar kelimesi eklenmiştir.

var anahtar kelimesi sayesinde, değişkenin tipi atandığı değerden otomatik olarak çözümleniyor.

İsimsiz Tipler (Anonymous Types) IDisposable interface’ini uygulamadığı için, Disposable olamazlar.

Eğer yukarıdaki örneği geleneksel kodlama teknikleri ile yazacak olsaydık;

public class HataBilgi
{
	private string _Mesaj = string.Empty;
	private DateTime _Tarih = DateTime.Now;
	private string _Yer = string.Empty;

	public string Mesaj
	{
		get
		{
			return _Mesaj;
		}
		set
		{
			_Mesaj = value;
		}
	}

	public DateTime Tarih
	{
		get
		{
			return _Tarih;
		}
		set
		{
			_Tarih = value;
		}
	}

	public string Yer
	{
		get
		{
			return _Yer;
		}
		set
		{
			_Yer = value;
		}
	}

	public HataBilgi(string Mesaj, DateTime Tarih, string Yer)
	{
		this.Mesaj = Mesaj;
		this.Tarih = Tarih;
		this.Yer = Yer;
	}
}

public class KullaniciBilgi
{
	private int _Id = 0;
	private string _AdSoyad = string.Empty;
	private string _Yonetici = string.Empty;

	public int Id
	{
		get
		{
			return _Id;
		}
		set
		{
			_Id = value;
		}
	}

	public string AdSoyad
	{
		get
		{
			return _AdSoyad;
		}
		set
		{
			_AdSoyad = value;
		}
	}

	public string Yonetici
	{
		get
		{
			return _Yonetici;
		}
		set
		{
			_Yonetici = value;
		}
	}

	public KullaniciBilgi(int Id, string AdSoyad, string Yonetici)
	{
		this.Id = Id;
		this.AdSoyad = AdSoyad;
		this.Yonetici = Yonetici;
	}
}

public class HataLoglama
{
	HataBilgi Hata = new HataBilgi("Hata Mesajının Kendisi", DateTime.Now, "XClass.YMethod");
	KullaniciBilgi Kullanici = new KullaniciBilgi(42, "Engin Polat", "Ali Veli");

	string Loglanacak = string.Format("Hata Mesajı: {0}\nTarih: {1} {2}\nHatanın Oluştuğu Yer: {3}\n\nKullanıcıId: {4}\nKullanıcı Adı: {5}\nYöneticisi: {6}", Hata.Mesaj, Hata.ToShortDateString(), Hata.Tarih.ToLongTimeString(), Hata.Yer, Kullanici.Id, Kullanici.AdSoyad, Kullanici.Yonetici);

	File.WriteAllText(Loglanacak, @"C:\Log\Log.txt");

	MessageBox.Show(Hata.Mesaj, Hata.Tarih);
}

İsimsiz Tip yeteneklerini kullanarak yazdığımızda ise;

public class HataLogla()
{
	var Hata = new { Mesaj = "Hata Mesajının Kendisi", Tarih = DateTime.Now, Yer = "XClass.YMethod" };
	var Kullanici = new { Id = 42, AdSoyad = "Engin Polat", Yonetici = "Ali Veli" };

	string Loglanacak = string.Format("Hata Mesajı: {0}\nTarih: {1} {2}\nHatanın Oluştuğu Yer: {3}\n\nKullanıcıId: {4}\nKullanıcı Adı: {5}\nYöneticisi: {6}", Hata.Mesaj, Hata.ToShortDateString(), Hata.Tarih.ToLongTimeString(), Hata.Yer, Kullanici.Id, Kullanici.AdSoyad, Kullanici.Yonetici);

	File.WriteAllText(Loglanacak, @"C:\Log\Log.txt");

	MessageBox.Show(Hata.Mesaj, Hata.Tarih);
}

Aradaki fark açıkça ortada!