Giriş
await, async ile beraber ya da tek başına kullanılabilir.
Tek Başına await yazısına göz atabilirsiniz.
asycn Best Practices
Microsoft'un önerisi
şöyle.
-change the signature of the async methods so that they return Task or Task<> (in TypeScript, that'd be a Promise<>)
-change the names of the async methods to end with xxxAsync()
async Return Type
async metodlar genelde Task, Task<T> veya void
dönerler.
async Method ve ref Type
async metod içind ref type kullanılamaz.
Örnek
Elimizde şöyle bir kod
olsun.
async Task MethodAsync(ref bool isCancelled)
{
...
}
Şöyle bir hata
alırız.
CS1988: Async methods cannot have ref, in or out parameters
async ve await ikilisi
async ve await Continuation yapılacağı zaman kullanılır. Yani şu async işaretli bir metod içinde bulunan şu kod
parçası
var str = await SomeFuncAsync() //returning "test";
this.textBox1.Text = str;
aslında şuna
eşittir.
Task.Factory.StartNew(() => { return "test"; } )
.ContinueWith(task => { this.textBox1.Text = task.Result; },
CancellationToken.None,
TaskContinuationOptions.None,
TaskScheduler.FromCurrentSynchronizationContext());
async ve StateMachine
async kelimesini gören derleyici
System.Runtime.CompilerServices.AsyncStateMachineAttribute
sınıfını kullanarak bir State Machine
oluşturur.
async Event Handler
async Event Handler yazısına taşıdım.
async lambda
async Event Handler yazısına taşıdım.
deadlock
async metodlar eğer yanlış kullanılırsa deadlock'a sebep olabiliyor ancak .Net içindeki sınıflar async/await kullanmadıkları için rahatça
kullanılabilir.
async metod içinde await ne işe yarar
await Task'ın bitmesini beklemek için kullanılır. await ile Task.Factory. Start
kullanılabilir.
public async Task FooAsync()
{
int value = await Task.Factory.StartNew(
() => DoSomething(), TaskCreationOptions.LongRunning);
}
veya Task.Run'da
kullanılabilir.
public async Task FooAsync()
{
int value = await Task.Run(() => DoSomething());
}
veya asenkron çalışan bir metod çağrısı yapılır. Şöyle
yaparız.
public static async Task <string> job()
{
...
await Task.Delay(2000);
...
}
Eğer bunları yapmazsak şöyle bir hata
alırız.
Severity Code Description Project File Line Column Warning CS1998 This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
Örneğin aşağdaki kod bu hatayı
verir.
public async Task<int> GetData() {
return 1;
}
await çağrıları Short Circuit Evaluation Yaparlar
Örnek
Elimizde şöyle bir kod
olsun. Çıktı olarak sadece "Tested" alırız. Çünkü ilk await false döner.
async Task Main()
{
if (await first_check() && await second_check())
{
Console.WriteLine("Here?");
}
Console.WriteLine("Tested");
}
Task<bool> first_check() => Task.FromResult(false);
Task<bool> second_check() {
Console.WriteLine("second_check");
return Task.FromResult(true);
}
async metod içinde await ve SyncronizationContext
await çağrılınca altta devam eden kodun kendisini çağıran thread içinde çalışması için SynchronizationContext'i saklar. Şöyle bir kodumuz
olsun.
public async Task X()
{
A();
await BAsynch();
C();
}
await çağrısından sonra gelen C() şu hale
getirilir.
public Task X()
{
A();
return BAsynch().ContinueWith(()=>{ C(); })
}
Dolayısıyla artık Invoke(), BeginInvoke() gibi metodları kullanmaya gerek
kalmıyor.
SyncronizationContext Her Thread'de Bulunur mu ?
SynchronizationContext GUI thread'lerinde bulunur ancak konsol thread'lerinde bulunmaz. Dolayısıyla konsolda çalışan bu örnekte farklı sonuçlar
görebiliriz.
static void Main(string[] args)
{
Console.WriteLine("Main: " + Thread.CurrentThread.ManagedThreadId);//8
MainAsync(args).Wait();
Console.WriteLine("Main End: " + Thread.CurrentThread.ManagedThreadId);//8
Console.ReadKey();
}
static async Task MainAsync(string[] args)
{
Console.WriteLine("Main Async: " + Thread.CurrentThread.ManagedThreadId);//8
await thisIsAsync();
}
private static async Task thisIsAsync()
{
Console.WriteLine("AsyncStart: " + Thread.CurrentThread.ManagedThreadId);//8
await Task.Delay(1);
Console.WriteLine("AsyncEnd: " + Thread.CurrentThread.ManagedThreadId);//9
}
async metod içinde await ve Exception
Şöyle
yaparız.
async void btncheckPassword_Click(object sender, EventArgs e)
{
try
{
await Task.Run(
() =>
{
try
{
... //Exception thrown from async method
}
catch
{
throw new XXX(); //Catch and throw XXX
}
});
}
catch (XXX e) //Code is executed in SynchronizationContext
{
...
}
}