12 Ocak 2018 Cuma

Task Sınıfı

Giriş
Bu sınıfları kullanmak için şu satırı dahil ederiz. Bu sınıf .Net 4.0 ile geldi. Daha önceki sürümlerde Thread ile çalışmaktan başka çare yok.
using System.Threading.Tasks;
Constructor - Action
Şöyle yaparız.
var task = new Task<Data>(() => ...);
Bu constructor Task'ı başlatmaz. Hemen başlatmak için Task.Start() veya Task.Factory.StartNew() veya Task.Run() metodlarından birisini kullanmamız gerekir.

AsAsync metodu 
Şöyle yaparız.
public IAsyncAction FindPerson(string personId)
{
  Task t = new Task(() =>
  {
    //Search the person and write to screen 
  });
  t.Start();
  return t.AsAsyncAction();
}
CompletedTask Alanı
Örnek ver

ConfigureAwait metodu 
async metodlarda await'ten sonra gelen kodun hangi thread tarafından çağrılacağını ayarlar. Aşağıdaki kod UI dışından bir yerde çalıştığı için ConfigureAwait(false) yapılıyor. Böylece TestTask()'ı çağıran thread return "TestTask" kısmını çalıştırıyor.
async Task<string> TestTask()
{
    await Task.Delay(2000).ConfigureAwait(false);

    return "TestTask";
}
ContinueWith metodu - Action
Şöyle yaparız. ContinueWith metoduna geçilen parametre ana Task nesnesidir.
var t1 = new Task(() => ...);
var t2 = t1.ContinueWith((t) => ...);
t1.Start();
ContinueWith metodu - Action + TaskScheduler
Örnek
Eğer task UI thread içinde başlatıldıysa arka plan iş bittikten sonra UI nesnesini güncellemek için şöyle yaparız.
public Action Worker = ...;
Task.Factory
    .StartNew(Worker)
    .ContinueWith(t => 
    { 
      ...
    }, TaskScheduler.FromCurrentSynchronizationContext()
);
Örnek
Şöyle yaparız

Delay metodu 
Task.Delay ile Thread.Sleep hemen hemen aynı işi yapar. Yani thread'i bir müddet uyutur. Aslında Task.Delay altta System.Threading.Timer sınıfını kullanıyor. Açıklaması şöyle
// on line 5893
// ... and create our timer and make sure that it stays rooted.
if (millisecondsDelay != Timeout.Infinite)
{
  promise.Timer = new Timer(...);
  promise.Timer.KeepRootedWhileScheduled();
}
Thread.Sleep()'ten farklı olarak Task.Delay süre bitmeden iptal edilebilir. Task.Delay .Net 4.5 ile geliyor. Daha önceki ortamlarda aşağıdakine benzer bir kod kullanılabilir.
public static Task Delay(double milliseconds)
{
    var tcs = new TaskCompletionSource<bool>();
    System.Timers.Timer timer = new System.Timers.Timer();
    timer.Elapsed+=(obj, args) =>
    {
        tcs.TrySetResult(true);
    };
    timer.Interval = milliseconds;
    timer.AutoReset = false;
    timer.Start();
    return tcs.Task;
}
Çok hızlı dönen döngülerde özellikle GUI güncellemesi yapılıyorsa bir süre beklemek GUI'nin tıkanmasını engeller.
while (true)
{
  var updateFrequency = Task.Delay(1000);
  if (bStreaming == true)
  {
     textboxTX.Invoke(new Action(() => textboxTX.Text = ...));
     textboxTY.Invoke(new Action(() => textboxTY.Text = ...));
     textboxTZ.Invoke(new Action(() => textboxTZ.Text = ...));
    }
    await updateFrequency;
}
Task.Delay eğer verilen süre 0 ise çalışmaz. Aşağıdaki örnekte callback() metodunu çağırmadan önce verilen süre kadar bekler. Eğer süre 0 ise Yield kullanmak gerekir.
async void setTimeout(dynamic callback, int timeout)
{
    if(timeout > 0)
    {
        await Task.Delay(timeout);
    }
    else
    { 
        await Task.Yield();
    }

    callback();
}
FromResult metodu
Açıklaması şöyle
Creates a Task that's completed successfully with the specified result.
Şöyle yaparız.
Task t = Task.FromResult<bool>(true);
Şu kod ile aynı kapıya çıkar.
Task.Run(() => true);
IsCompleted Alanı
Task'ın bitip bitmediğini belirtir. Örnekte Task bitmediyse, örneğin exception aldıysa IsCompleted false döndüğü için default bir değer döndürülür.
public Task<List<string>> LoadExample()
{
  Task<List<string>> task = LoadMyExampleTask();
  return task.ContinueWith(t => t.IsCompleted ? t.Result : default(List<string>));
}
Run metodu 
Task.Run metodu yazısına taşıdım.

WaitAll metodu 
Task.WaitAll metodu yazısına taşıdım.

WhenAll metodu - .Net 4.5 ile
WaitAll metodunun tersine tüm Task'ların sonuçların alabilmemizi sağlar. await ile kullanılmak üzere tasarlanmıştır.

Örnek
Tüm sonuçları bir diziye almak için şöyle yaparız.
object[] allObjectAttributes = await Task.WhenAll(
    Task.Run(() => ...),
    Task.Run(() => ...),
    Task.Run(() => ...),
    Task.Run(() => ...)
);
Örnek
Şöyle yaparız.
public static async Task Run()
{
  List<Task> tasks = new List<Task>();

  Task t1 = Task.Run(()=>...);
  Task t2 = Task.Run(() =>...);

  tasks.Add(t1);
  tasks.Add(t2);

  await Task.WhenAll(tasks);  //ERROR IS THROWN HERE
  Console.WriteLine("All tasks completed");
}
Örnek
Linq ile tüm sonuçları dolaşmak için şöyle yaparız.
private static async Task<string> checkAvaibleAsync(string url)
{
  using (var client = new HttpClient())
  {
    string htmlCode = await client.GetStringAsync(url); 

    if (...)
      return url;
    else
      return null;
  }
}
Bu metodu şöyle çağırırız.
private static async Task<string[]> searchForLinksAsync()
{
  string url = "http://www.xxxx.pl/xxxx/?action=xxxx&id=";

  var tasks = Enumerable.Range(0, 2500).Select(i => checkAvailableAsync(url + i));
  var results = await Task.WhenAll(tasks);
  var listOfUrls = results.Where(x => x != null).ToArray();

  Console.WriteLine(listOfUrls.Length);
  Console.ReadLine();
}




Hiç yorum yok:

Yorum Gönder