İlkay İlknur

just a developer...

Windows Runtime Componentlerinde Asenkron İşlemler - C# 5.0

Bir önceki yazimizda Windows Runtime Componentlerini inceledikten sonra simdi sira geldi WinRT Component'leri gelistirme sirasinda karsimiza siklikla çikabilecek olan bir durumu incelemeye. :) Bildigimiz gibi Windows 8 ile beraber gelen WinRT altyapisi içerisinde bulunan pek çok yapi asenkron sekilde çalismak üzere tasarlandi. Hatta bu asenkron altyapiyi kullanmayi kolaylastirmak için de C# 5.0 ile beraber gelen asenkron programlama yeniliklerini kullanmaktayiz.

Hal böyle olunca Windows Runtime Componentleri içerisinde de asenkron olarak çalisacak yapilar gelistirmek artik neredeyse kaçinilmaz bir hal aldi. Bu yazimizin konusu da Windows Runtime Componentleri içerisinde asenkron sekilde çalisacak yapilari nasil gelistirecegimiz ile ilgili.

.NET Framework içerisinde asenkron islem diyince artik bir çirpida aklimiza gelen tip Task tipi olmakta. Önceki yazilarimizdan da hatirlayacagimiz üzere asenkron islemlerin yönetimini Task tipi üzerinden kolaylikla yapabiliyoruz. Peki Windows Runtime Component'i gelistirme tarafina geçtigimizde Task tipi hala daha orada mi yoksa karsimiza baska seyler mi çikiyor hemen durumu bir örnek yaparak inceleyelim.

Örnek olarak basit bir sekilde bir RSS adresinden ilgili contenti asenkron olarak download eden bir metot yazacagiz.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Windows.Foundation;

namespace AsyncWinRTComponent
{
    public sealed class AsyncHelper
    {
        public async static Task<string> DownloadRSSAsync()
        {
            HttpClient client = new HttpClient();

            var result = await client.GetAsync("http://www.ilkayilknur.com/feed");

            return await result.Content.ReadAsStringAsync();
        }
    }
}
Koda baktigimizda artik alistigimiz asenkron implementasyonlardan hiç bir farki yokmus gibi görünüyor :) Öyleyse kodu derleyelim bakalim herhangi bir sorunla karsilasacak miyiz :)

Error 1 Method 'AsyncWinRTComponent.AsyncHelper.DownloadRSSAsync()' has a parameter of type 'System.Threading.Tasks.Task<System.String>' in its signature. Although this generic type is not a valid Windows Runtime type, the type or its generic parameters implement interfaces that are valid Windows Runtime types. Consider changing the type 'Task' in the method signature to one of the following types instead: Windows.Foundation.IAsyncAction, Windows.Foundation.IAsyncOperation, or one of the other Windows Runtime async interfaces. The standard .NET awaiter pattern also applies when consuming Windows Runtime async interfaces. Please see System.Runtime.InteropServices.WindowsRuntime.AsyncInfo for more information about converting managed task objects to Windows Runtime async interfaces. C:\Users\ilkayilknur\AppData\Local\Temporary Projects\AsyncWinRTComponent\Class1.cs 39 42 AsyncWinRTComponent

Upps :) Bu hatanin artik ne demek oldugunu biliyoruz bir önceki yazimizdan. Bu demek oluyor ki Task tipi WinRT tarafinda bulunan bir tip degil. Sadece .NET Framework tarafinda bulunuyor ve asenkron olarak gelistirdigimiz  public metotlardan Task tipini dönemiyoruz. Peki ne yapacagiz ?

IAsyncAction ve IAsyncOperation<T> Interfaceleri

Windows Runtime tarafinda asenkron islemler dedigimizde de karsimiza Task tipi yerine IAsyncAction ve IAsyncOperation<T> interfaceleri çikiyor. IAsyncAction interface'i herhangi bir deger döndürmeyen asenkron islemlerin yönetiminde kullanilirken IAsyncOperation<T> interface'i de asenkron islem sonucu bir deger dönülen metotlarda kullanilmakta. Ayni zamanda IAsyncAction interface'i içerisinde yaptiginiz asenkron çagri ile ilgili olarak progress bilgisini de almamiz mümkün degil.

Simdi yapmis oldugumuz örnegimize dönersek asenkron metodumuz içerisinde islem sonlandiktan sonra bir deger döndürdügümüz için IAsyncOperation<T> interface'ini kullanmamiz gerekmekte. Peki kullanimi nasil gerçeklestirecegiz ? Burada en önemli konu bu. Çünkü metodumuzu async modifier'i ile tanimladik. Ancak metottan Task tipi dönemiyoruz ve Windows Runtime Component'i içerisinden de metodu disari açmamiz için de Task tipi yerine IAsyncOperation<T> dönmemiz gerekmekte. Yani isler oldukça karisik. :D

Simdi ilk olarak parça parça ilerleyelim ve yazmis oldugumuz metodu public yerine private olarak tanimlayalim ve metodu Windows Runtime Component'i içerisinde çalisacak olan bir iç metot olarak düsünelim.

private async static Task<string> DownloadRSSAsyncInternal()
{
    HttpClient client = new HttpClient();

    var result = await client.GetAsync("http://www.ilkayilknur.com/feed");

    return await result.Content.ReadAsStringAsync();
}

Evet simdi Windows Runtime Component'imiz basarili bir sekilde derlenebiliyor çünkü Task tipini döndügümüz metodumuzu private olarak tanimladik. (Metot isminin sonuna Internal kelimesini de yerlestirdik ki disari açtigimiz metotta yine DownloadRSSAsync ismini kullanabilelim ;) )

Simdi DownloadAsyncRSS isimli metodumuzu IAsyncOperation<T> dönecek sekilde tanimlayalim ve esas önemli kisma gelelim.

Bu yazdigimiz metot içerisinde de aslinda elimizdeki bulunan DownloadRSSAsyncInternal isimli metottan dönen Task tipini IAsyncOperation<T> interface'ine çevirebilirsek isimizi bitirebiliriz gibi görünüyor ne dersiniz ? Acaba elimizde bulunan bir Task tipini IAsyncOperation<T>'a çevirebilecek bir yapi var midir bakalim.

Iste aradigimiz tam da böyle birsey :) Windows Runtime içerisindeki yapilara baktigimizda içerisinde .NET Framework tipleri ve WinRT tipleri arasinda hizli geçisler yapabilecegimiz pek çok extension metot mevcut. Bu çerçevede elimizde bulunan Task tipinden de IAsyncOperation<T> üretmek için de AsAsyncOperation isimli bir metot WinRT içerisinde bulunmakta. Ayni sekilde elimizde bulunan Task tipinden IAsyncAction üretmemiz de mümkün. Öyleyse yazacagimiz Windows Runtime Component'in son hali su sekilde olacak.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Windows.Foundation;

namespace AsyncWinRTComponent
{
    public sealed class AsyncHelper
    {
        private async static Task<string> DownloadRSSAsyncInternal()
        {
            HttpClient client = new HttpClient();

            var result = await client.GetAsync("http://www.ilkayilknur.com/feed");

            return await result.Content.ReadAsStringAsync();
        }

        public static IAsyncOperation<string> DownloadRSSAsync()
        {
            return DownloadRSSAsyncInternal().AsAsyncOperation();
        }
    }
}

Gördügünüz gibi Windows Runtime Componentleri içerisinde asenkron metotlar yazip disari açmak da oldukça kolay. Özellikle .NET Framework ile WinRT tipleri arasindaki geçisleri yapmak gördügünüz gibi extension metotlarla oldukça kolaylasmis durumda. Bu extension metotlar sadece asenkron programlamada kullandigimiz tipler için degil ayni zamanda Streamler gibi yapilarda da islerimizi oldukça kolaylastirmakta. Tavsiyem eger WinRT tarafinda bir tipte sikisip kaldiysaniz ve bir islemi nasil yapacaginiza tam olarak emin degilseniz ve bu isi .NET Frameworkle hemen çözebileceginizi düsünüyorsaniz elinizdeki Windows Runtime tipini .NET Framework tipine çeviren bir extension metot olup olmadigini mutlaka arastirin ;)

Umarim faydali olmustur.

Hepinize kolay gelsin,

Not: Blogumu RSS veya sosyal sitelerden takip etmekte sikinti çekenler için blogumu mail ile de takip edebilirsiniz. Buradaki linke tiklayarak kaydinizi yapabilirsiniz. 



Yorum Gönder