12 Mart 2015 Perşembe

Continuation

Continuation Nedir?
Continuation bir thread'in işini bitirdikten sonra, programın nereden çalışmaya devam edeceğini gösteren yapıdır.

Bir çok dilde continuation yapısını destekleniyor.

C#
asynch ve await
await, async metod ile beraber kullanılırsa await çağrısından sonra gelen kod continuation olarak işletilir. await Task'ın bitmesini bekler. Buraya kadar herşey Task'ın bitmesini beklemek ile aynı. Farklı olan şey , await çağrısından sonra gelen kod, compiler tarafından üretilen state machine sayesinde await çağrısını yapan thread içinde çalışması.

Bir metod içinde await kullanılabilmesi için metodun async olarak işaretli olması gerekir.
async void button1_Click(object sender, EventArgs e)
async şöyle açıklanıyor

By using the async modifier, you specify that a method, lambda expression, or anonymous method is asynchronous. If you use this modifier on a method or expression, it's referred to as an async method.

Eğer metod async değilse aşağıdaki hatayı alırız.
The 'await' operator can only be used within an async method. Consider marking this method with the 'async' modifier and changing its return type to 'Task'
await örneği
private async void Button_Click(object sender, RoutedEventArgs e)
  {
     string outputString = (await Authentication(usernameTextBox.Text));

     MessageBox.Show(outputString);
  }

  private Task<bool> Authentication(string username)
  {
     return Task.Run(() => CheckIfNameExistsInDatabaseOnServer(username));
  }

  private bool CheckIfNameExistsInDatabaseOnServer(string username)
  {
     //Pretend to pass details and wait for a response
     Thread.Sleep(5000);

     return (username == "Will");
  }

await'in arka arkaya çağrılması
Örnek'te 3 tane Task için await çağırılıyor.
var Task1 = WebService1.Call();
var Task2 = WebService2.Call();
var Task3 = WebService3.Call();

var Data1 = await Task1;
var Data2 = await Task2;
var Data3 = await Task3;

Bu kod Task1'in ThreadPool içinde çalışması, bitince Task2'nin ThreadPool içinde çalışması, o da bitince Task3'ün ThreadPool içinde çalışması anlamına gelir.

await ve Task.WhenAll
Eğer amacımız tüm Task'ları paralel çalıştırmak ise şöyle yapabiliriz.
var Data = await Task.WhenAll(WebService1.Call(), 
    WebService2.Call(), 
    WebService3.Call());
Böylece 3 Task paralel çalıştıktan sonra await'in ardından gelen Continuation işletilir.

await ve Task.WhenAny
WhenAny bir task listesindeki herhangi birisinin dönmesini bekler. Basit bir örnek.
// Create a list of tasks for each string in empList
List<Task> empTaskList = empList.Select(emp => Task.Run(() => ComputeSalary(emp)))
                                .ToList();

// Give me the task that finished first.
var firstFinishedTask = await Task.WhenAny(empTaskList); 
Eğer task'in belirtilen süre içinde bittiğini kontrol etmek istersek şöyle yaparız. WhenAny() aynı zamanda iki task'ı başlatır. await ile kodumuz bir task'ın bitmesini bekler. WhenAny() ilk task biter ise timeout olmuştur diye kabul eder ve tru döner.
Task delayedTask = Task.Delay(TimeSpan.FromMinutes(5));
Task workerTask = Task.Factory.StartNew(() =>
{
     Aspose.Words.Document doc = new Aspose.Words.Document(inputFileName);
     doc.Save(Path.ChangeExtension(inputFileName, ".pdf"));
});

if (await Task.WhenAny(delayedTask, workerTask) == delayedTask)
{
   // We got here because the delay task finished before the workertask.
}
else
{
   // We got here because the worker task finished before the delay.
}
sync over asynch anti pattern
asynch bir metodun synch yapılmaya çalışılması anlamına geliyor. Kodu çoklamama için yapılan iyi niyetli bu girişim GUI'den yapılırsa deadlock'a sebep olabilir. Örnekte yanlış kod var.
public override int Read(byte[] buffer, int offset, int count)
{
    return ReadAsync(buffer, offset, count).Result;
}
Açıklaması şöyle. Bu kod GUI'de çağrılırsa, thread pool'a ReadAsync işlemini başlatır. Daha sonra GUI thread'i Result üzerinde bloke olur. ReadAsynch bitince await'in ardından gelen kod GUI thread'ine post edilmeye çalışılır ancak GUI thread'i bloke olduğu için post işlemi GUI thread'ini bekler. GUI thread'i de Task'ı bekler ve deadlock oluşur.





Hiç yorum yok:

Yorum Gönder