Task etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
Task etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

26 Kasım 2020 Perşembe

Task Sınıfı Converging Back to The Calling Thread

Giriş
Açıklaması şöyle
On the same threads synchronization topic, the Task library enables several ways to wait until other tasks have finished their execution. This is a significant expansion of the usage of the Thread.Join concept.

The methods Wait , WaitAll , and WhenAny are different options to hold the calling thread until other threads have finished.
Wait metodu
Örnek ver

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

WhenAny metodu
Örnek ver

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

Task Sınıfı Continuation

Giriş
Açıklaması şöyle
Before using the Task library, we had to use callback methods, but with TPL, it is much more comfortable. A simple way to chain threads and create a sequence of execution can be achieved by using Task.ContinueWith method. The ContinueWith method can be chained to the newly created Task or defined on a new Task object.

Another benefit of using the the the ContinueWith method is passing the previous task as a parameter, which enables fetching the result and processing it.
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 + TaskContinuationOptions
Açıklaması şöyle
The ContinueWith method accepts a parameter that facilitates the execution of the subsequent thread, TaskContinuationOptions, that some of its continuation options I find very useful:

- OnlyOnFaulted/NotOnFaulted (the continuing Task is executed if the previous thread has thrown an unhandled exception failed or not);
- OnlyOnCanceled/NotOnCanceled (the continuing Task is executed if the previous thread was canceled or not).

You can set more than one option by defining an OR bitwise operation on the TaskContinuationOptions items.
Örnek
Şöyle yaparız
// Initiate a library account object
LibraryAccount libraryAccount = new LibraryAccount(booksAllowance);
Task<int> task = Task.Factory.StartNew<int>(() =>{
  // The first task withdraws books
  libraryAccount.WithdrawBooks(booksToWithdraw);
  return libraryAccount.BorrowedBooksCount;
  })
  .ContinueWith<int>((prevTask) => {
    // Fetching the result from the previous task
    int booksInventory = prevTask.Result;
    Trace.WriteLine($"Current books inventory count {booksInventory}");
    // Return the books back to the library
    libraryAccount.ReturnBooks(booksToWithdraw);
    return libraryAccount.BorrowedBooksCount;
  }, // Set the conditions when to continue the subsequent task
  TaskContinuationOptions.NotOnFaulted | 
  TaskContinuationOptions.NotOnCanceled |
  TaskContinuationOptions.OnlyOnRanToCompletion);
  
// Wait for the task to end before continuing the main thread.
task.Wait();
// The actual number of books should remain the same
Assert.Equal(task.Result, booksAllowance);
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

ContinueWhenAll metodu
Açıklaması şöyle
Besides calling the ContinueWith method, there are other options to run threads sequentially. The TaskFactory class contains other implementations to continue tasks, for example, ContinueWhenAll or ContinueWhenAny methods. The ContinueWhenAll method creates a continuation Task object that starts when a set of specified tasks has been completed. In contrast, the ContinueWhenAny method creates a new task that will begin upon completing any task in the set that was provided as a parameter.


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;
Açıklaması şöyle
The Task Parallel Library (TPL) was introduced in .NET 4.0 as a significant improvement in running and managing threads compared to the existing System.Threading the library earlier; this was the big news in its debut.

In short, the Task Parallel Library (TPL) provides more efficient ways to generate and run threads than the traditional Thread class. Behind the scenes, Tasks objects are queued to a thread pool. This thread pool is enhanced with algorithms that determine and adjust the number of threads to run and provide load balancing to maximize throughput. These features make the Tasks relatively lightweight and handle effectively threads than before.

The TPL syntax is more friendly and richer than the Thread library; for example, defining fine-grained parallelism is much easier than before. Among its new features, you can find partitioning of the work, taking care of state management, scheduling threads on the thread pool, using callback methods, and enabling continuation or cancellation of tasks.

The main class in the TPL library is Task; it is a higher-level abstraction of the traditional Thread class. The Task class provides more efficient and more straightforward ways to write and interact with threads. The Task implementation offers fertile ground for handling threads.
Önemli Kavramlar
Task'ı kullanabilmek için şu kavramları bilmek gerekiyor
1. Tasks continuation
2. Paralleling tasks
3. Canceling tasks
4. Synchronizing tasks
5. Converging tasks back to the calling thread
İkinci madde için Parallel.Invoke(), Parallel.ForEach() ve Parallel.For() kullanılır
Dördüncü madde için TaskCompletionSource kullanılır
Beşinci madde için Task.Wait(), Task.WaitAll(), Task.WhenAny() ve Task.WhenAll() kullanılır

Constructor - Action
Açıklaması şöyle. 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.
The basic constructor of a Task object instantiation is the delegate Action, which returns void and accepts no parameters.
Örnek
Şöyle yaparız.
var task = new Task<Data>(() => ...);
Constructor - Action<Object> + Object
Sadece Action alan constructor'a göre çok da bir fayda sağlamıyor.

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
Task Sınıfı Continuation yazısına taşıdım

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.

Wait metodu

WaitAll metodu 
Task Sınıfı Converging Back to The Calling Thread yazısına taşıdım

WhenAny metodu

WhenAll metodu

15 Eylül 2017 Cuma

Task.Run metodu

Giriş
Açıklaması şöyle
A Task.Run or Task.Factory.StartNew may start executing at any time (e.g. if a thread from the pool is idle), even if nothing is waiting for it.
Action Parametresi - Lambda
Kullanımı çok basit. Şöyle yaparız. Verilen işin thread pool içinde çalışmasını sağlar.
Task.Run(() => {...});
Task.Run altta şöyle bir kod çalıştırıyor.
Task.Factory.StartNew(someAction, 
  CancellationToken.None, 
  TaskCreationOptions.DenyChildAttach,
  TaskScheduler.Default);
Action Parametresi - async metod
Bu kullanımı hiç anlamadım. asenkron metodu senkron haline getiriyor ve yapılmamalı deniliyor. Açıklaması şöyle
You should not hide an asynchronous implementation behind a synchronously running method
Örnek
Şöyle yaparız.
Task.Run(async () => await MyAsyncTask());
ConcurrentBag<int> bag = new ConcurrentBag<int> ();

async Task MyAsyncTask()
{
  await Task.Delay(random.Next(1000));
  bag.Add (random.Next (10));
}
Örnek
Elimizde şöyle bir metod olsun
public async Task<Foo> GetFooAsync();
Senkron hale getirmek için şöyle yaparız
Task.Run(async () => await GetFooAsync());
Döndürülen Nesne Tipi
Task.Run metoduna döndürülen nesne tipini yazamaya gerek yok. Derleyici bizim için belirler. Şöyle yaparız.
Task<string> Foo() 
{
  return Task.Run(()=>
  {
    SomeLongRunningMethod();
    return "Hello";
  });
}
Exception
MSDN örneği şöyle
var myTask = Task.Run(() =>
    {
        throw new Exception("test");
    });
try
{
    myTask.Wait();
}
catch (Exception e)
{
    return false;
}
Run metodu exception fırlatırsa, dışarıdaki kod exception'ı görebilir. Açıklaması şöyle.
task.Wait()  Rethrows any exceptions

task.Result  Rethrows any exceptions