Zaman uyumsuz görev programlama modeli

Zaman uyumsuz programlama kullanarak performans sorunlarını önleyebilir ve uygulamanızın genel yanıt verme becerisini geliştirebilirsiniz. Ancak, zaman uyumsuz uygulamalar yazmaya yönelik geleneksel teknikler karmaşık olabilir ve bu nedenle yazılmaları, hataların ayıklanması ve bakım yapılması zorlaşabilir.

C# 5, .NET Framework 4.5 ve daha üst bir sürümü, .NET Core ve Windows Runtime'da zaman uyumsuz desteklerden yararlanan basitleştirilmiş bir zaman uyumsuz programlama yaklaşımını benimser. Derleyici, normalde geliştiricinin yaptığı zor işi yapar ve uygulamanız zaman uyumlu koda benzer bir mantıksal yapıyı korur. Sonuç olarak, zaman uyumsuz programlama avantajlarının tamamını çok daha az çaba harcayarak elde edebilirsiniz.

Bu konu zaman uyumsuz programlamanın ne zaman ve nasıl kullanılması gerektiği hakkında genel bakış içerir ve ayrıntılar ve örnekler içeren destek konularına bağlantılar sunar.

Zaman uyumsuzluk yanıt hızını iyiler

Zaman uyumsuzluğun, web erişimi gibi engelleyici olabilecek etkinlikler için temel öneme sahip olması gerekir. Web kaynağına erişim bazen yavaş veya gecikmeli olabilir. Zaman uyumlu bir işlemde böyle bir etkinlik engellenirse, uygulamanın tamamı beklemeli. Uygulama, zaman uyumsuz bir işlemde olası engelleme görevi sona erinceye kadar web kaynağına bağlı olmayan diğer işlerle devam eder.

Aşağıdaki tabloda, zaman uyumsuz programlamanın yanıt verme hızını geliştirdiği genel alanlar gösterilmektedir. .NET ve Windows Runtime'dan listelenen API'ler, zaman uyumsuz programlamayı destekleyen yöntemler içerir.

Uygulama alanı Zaman uyumsuz yöntemlerle .NET türleri Windows Zaman uyumsuz yöntemlerle çalışma zamanı türleri
Web erişimi HttpClient Windows.Web.Http.HttpClient
SyndicationClient
Dosyalarla çalışma JsonSerializer
StreamReader
StreamWriter
XmlReader
XmlWriter
StorageFile
Görüntülerle çalışma MediaCapture
BitmapEncoder
BitmapDecoder
WCF programlama Zaman Uyumlu ve Zaman Uyumsuz İşlemler

Tüm kullanıcı arabirimi ilişkili faaliyetler genellikle tek bir iş parçacığını paylaştığından, zaman uyumsuzluğun kullanıcı arabirimi iş parçacığına erişen uygulamalar için özellikle önem taşıdığı kanıtlanmıştır. Herhangi bir işlem zaman uyumlu bir uygulamada engellenirse, tümü engellenir. Uygulamanız yanıt vermiyordur ve bunu uygulamanın beklediği değil de başarısız olduğu şeklinde yorumlayabilirsiniz.

Zaman uyumsuz yöntemleri kullandığınızda, uygulama arabirime yanıt vermeye devam eder. Bir pencereyi yeniden boyutlandırabilir veya simge durumuna küçültebilir ya da bitmesini beklemek istemiyorsanız kapatabilirsiniz.

Zaman uyumsuz tabanlı yaklaşım otomatik bir iletimin eşdeğerini, zaman uyumsuz işlemler tasarlarken seçebileceğiniz seçenekler listesine ekler. Diğer bir deyişle, geleneksel zaman uyumsuz programlamanın tüm avantajlarından yararlanabilirsiniz, buna rağmen geliştiricinin daha az çaba sarf etmesi gerekir.

Zaman uyumsuz yöntemleri yazmak kolaydır

C# dilindeki async ve await anahtar sözcükleri, zaman uyumsuz programlamanın merkezindedir. Bu iki anahtar sözcükleri kullanarak .NET Framework, .NET Core veya Windows Runtime'daki kaynakları kullanarak zaman uyumlu bir yöntem oluşturmak kadar kolay bir zaman uyumsuz yöntem oluşturabilirsiniz. anahtar sözcüğünü kullanarak tanımladığınız zaman uyumsuz async yöntemler, zaman uyumsuz yöntemler olarak adlandırılır.

Aşağıdaki örnekte zaman uyumsuz bir yöntem gösterilmektedir. Kodda yer alan neredeyse her şey size tanıdık geliyor.

C# dilinde async Windows Presentation Foundation await ile Zaman Uyumsuz programlama'dan indirilebilir tam bir örnek (WPF) bulabilirsiniz.

public async Task<int> GetUrlContentLengthAsync()
{
    var client = new HttpClient();

    Task<string> getStringTask =
        client.GetStringAsync("https://docs.microsoft.com/dotnet");

    DoIndependentWork();

    string contents = await getStringTask;

    return contents.Length;
}

void DoIndependentWork()
{
    Console.WriteLine("Working...");
}

Önceki örnekten birkaç uygulama öğrenildi. Yöntem imzasıyla çalışmaya başlama. Değiştiriciyi async içerir. Dönüş türü şu şekildedir Task<int> (daha fazla seçenek için "Dönüş Türleri" bölümüne bakın). Yöntem adı ile Async biter. yönteminin gövdesinde bir GetStringAsync Task<string> döndürür. Başka bir ifadeyle, göreviniz olduğunda bir await string ( ) contents alırsınız. Görevi bekleymeden önce, 'den'e bağlı olmayan işler string GetStringAsync yapabiliriz.

işlecine yakından await dikkatin. Askıya GetUrlContentLengthAsync alır:

  • GetUrlContentLengthAsync işlemi tamamlayana kadar getStringTask devam etmeyer.
  • Bu arada, denetim çağıranın GetUrlContentLengthAsync döndürür.
  • Denetim tamamlandığında burada getStringTask devam eder.
  • awaitİşleç daha sonra sonucu string 'den getStringTask alınır.

dönüş deyimi bir tamsayı sonucu belirtir. Beklenen tüm yöntemler GetUrlContentLengthAsync uzunluk değerini alın.

çağrısını yapmakla tamamlanmasını bekleyenler arasında herhangi bir iş yoksa, aşağıdaki tek deyimde çağırarak ve bekleerek GetUrlContentLengthAsync GetStringAsync kodunuzu basitleştirebilirsiniz.

string contents = await client.GetStringAsync("https://docs.microsoft.com/dotnet");

Aşağıdaki özellikler, önceki örneği zaman uyumsuz yöntem yapan özellikleri özetler:

  • Yöntem imzası bir değiştirici async içerir.

  • Zaman uyumsuz yöntemin adı kurala göre "Async" soneki ile sona erer.

  • Dönüş türü aşağıdaki türlerden biridir:

    • Task<TResult> yönteminizin, işlenenin türünde olduğu bir dönüş deyimi TResult varsa.
    • Task yönteminizin dönüş deyimi yoksa veya işleneni yoksa bir dönüş deyimi varsa.
    • void zaman uyumsuz olay işleyicisi yazıyorsanız.
    • Yöntemi olan diğer türler GetAwaiter (C# 7.0 ile başlayarak).

    Daha fazla bilgi için Dönüş türleri ve parametreler bölümüne bakın.

  • yöntemi genellikle en az bir ifade içerir ve bu ifade, beklenen zaman uyumsuz işlem tamamlandıktan sonra yöntemin devam await edinceye kadar bir nokta işaretler. Bu sırada yöntem askıya alınır ve denetim yöntemi arayana döner. Bu konunun sonraki bölümünde askıya alma noktasında neler olduğu gösterilmektedir.

Zaman uyumsuz yöntemlerde ne yapmak istediğinizi belirtmek için sağlanan anahtar sözcükleri ve türleri kullanırsınız ve denetim, askıya alınan bir yöntemde await noktasına geldiğinde olması gerekenlerin izlenmesi dahil olmak üzere geri kalan işlemleri derleyici yapar. Döngüler ve özel durum işleme gibi bazı rutin işlemlerin geleneksel zaman uyumsuz kodla yapılması zor olabilir. Zaman uyumsuz bir yöntemde, bu öğeleri olabildiğince zaman uyumlu çözümde yazarsınız ve sorun çözülür.

Önceki sürümlerde zaman uyumsuzluğu hakkında daha fazla bilgi .NET Framework bkz. TPL ve geleneksel .NET Framework programlama.

Zaman uyumsuz bir yöntemde ne olur?

Zaman uyumsuz programlama ile ilgili olarak anlamanız gereken en önemli şey, denetim akışının yöntemden yönteme nasıl geçtiğidir. Aşağıdaki diyagramda süreç boyunca size yol gösterebilirsiniz:

Zaman uyumsuz denetim akışının izleme gezintisi

Diyagramda yer alan sayılar, bir çağırma yöntemi zaman uyumsuz yöntemi çağıran aşağıdaki adımlara karşılık geldiğinde başlatılır.

  1. Çağıran yöntem, zaman uyumsuz yöntemi GetUrlContentLengthAsync çağırarak bekler.

  2. GetUrlContentLengthAsync bir örnek oluşturur ve bir web sitesinin içeriğini dize olarak HttpClient indirmek için zaman uyumsuz yöntemini GetStringAsync arar.

  3. içinde ilerlemesini GetStringAsync askıya alan bir şey olur. Bir web sitesinin indirmesini veya başka bir engelleyen etkinliği beklemesi gerekebilir. Kaynakların engellenmesini önlemek GetStringAsync için, çağıranın denetimine neden GetUrlContentLengthAsync olur.

    GetStringAsync bir Task<TResult> döndürür, TResult burada bir dizedir ve görevi GetUrlContentLengthAsync değişkenine getStringTask atar. Görev, çağrısı için devam eden işlemi temsil eder ve çalışma tamamlandığında gerçek bir dize değeri GetStringAsync üretme taahhüdü içerir.

  4. getStringTaskHenüz beklenmedi, GetUrlContentLengthAsync 'den elde edilen nihai sonuça bağlı olmayan diğer çalışmalarla devam GetStringAsync eder. Bu çalışma, zaman uyumlu yöntemine yapılan bir çağrıyla temsil DoIndependentWork edildi.

  5. DoIndependentWork , çalışmalarını yapan ve çağırana geri dönen zaman uyumlu bir yöntemdir.

  6. GetUrlContentLengthAsync ,'nin sonucundan sonuç almadan çalışamadan çalışmasına neden getStringTask oldu. GetUrlContentLengthAsync daha sonra indirilen dizenin uzunluğunu hesaplamak ve geri almak ister, ancak yöntem dizeyi içerene kadar bu değeri hesaplayamaz.

    Bu GetUrlContentLengthAsync nedenle, ilerlemesini askıya almak ve çağıran yöntemine denetim elde etmek için await işleci GetUrlContentLengthAsync kullanır. GetUrlContentLengthAsync``Task<int>çağırana bir döndürür. Görev, indirilen dizenin uzunluğu olan bir tamsayı sonucu verecek bir taahhüdü temsil eder.

    Not

    (ve GetStringAsync dolayısıyla getStringTask ) GetUrlContentLengthAsync beklenmeden tamamlanırsa denetim içinde GetUrlContentLengthAsync kalır. Çağrılan zaman uyumsuz işlem zaten tamamlandı ve nihai sonucu beklemek zorunda değilse askıya alma ve sonra geri dönme masrafı GetUrlContentLengthAsync getStringTask boşa GetUrlContentLengthAsync gider.

    Çağırma yönteminin içinde işleme düzeni devam eder. Çağıran, sonucu beklerken elde edilen sonucun sonucuna bağlı olmayan başka işler de yapar GetUrlContentLengthAsync veya çağıran hemen bekler. Çağıran yöntem için bekliyor GetUrlContentLengthAsync ve GetUrlContentLengthAsync GetStringAsync bekliyor.

  7. GetStringAsync tamamlar ve bir dize sonucu üretir. dize sonucu, çağrısı tarafından beklediğiniz GetStringAsync şekilde döndürülz. (Yönteminin 3. adımda zaten bir görev döndürüleni unutmayın.) Bunun yerine, dize sonucu yönteminin tamamlanmasını temsil eden görevde getStringTask depolanır. await işleci, elde edilen sonucu elde getStringTask ediyor. Atama deyimi, alınan sonucu 'a contents atar.

  8. dize GetUrlContentLengthAsync sonucu olduğunda yöntemi dizenin uzunluğunu hesaplar. Ardından işi de GetUrlContentLengthAsync tamamlanır ve bekleyen olay işleyicisi devam edebilir. Konunun sonundaki tam örnekte olay işleyicisinin uzunluk sonucundaki değeri aldığını ve yazdığını onaylayabilirsiniz. Zaman uyumsuz programlama konusunda yeniyseniz, zaman uyumlu ve zaman uyumsuz davranış arasındaki farkları değerlendirmek için bir dakikanızı ayırın. Zaman uyumlu yöntem, işi tamamlandığında döndürür (5. adım), ancak zaman uyumsuz bir yöntem işi askıya alındığında görev değeri döndürür (3 ve 6. adım). Zaman uyumsuz yöntem çalışmasını tamamladığında görev tamamlandı olarak işaretlenir ve varsa sonuç görevde depolanır.

API zaman uyumsuz yöntemleri

Zaman uyumsuz programlamayı destekleyen yöntemleri nerede GetStringAsync bulasanız diye merak ediyor olabilirsiniz. .NET Framework 4.5 veya üst ve .NET Core, ve ile birlikte birçok üye async await içerir. Bunları üye adına eklenen "Async" son ekini ve veya dönüş türüne göre Task tanıyamazsiniz. Task<TResult> Örneğin, sınıfı , ve gibi yöntemlerin yanı sıra , ve zaman System.IO.Stream CopyToAsync uyumlu yöntemleri ReadAsync WriteAsync CopyTo Read Write içerir.

Windows Çalışma Zamanı, uygulama uygulamalarında ve ile async kullanabileceğiniz await birçok Windows içerir. Daha fazla bilgi için bkz. UWP geliştirmesi için iş parçacığı ve zaman uyumsuz programlama, zaman uyumsuz programlama (Windows Store uygulamaları) ve Hızlı Başlangıç: C# dilinde zaman uyumsuz API'leri çağırma veya Visual Basic Windows Runtime'ın önceki sürümlerini kullanıyorsanız.

Iş parçacığı

Zaman uyumsuz yöntemlerin engelleyici olmayan işlemler olmaları amaçlanmıştır. Zaman await uyumsuz yöntemde yer alan bir ifade, beklenen görev çalışırken geçerli iş parçacığını engellemez. Bunun yerine ifade, yöntemin geri kalanını yöntemin devamı olarak imzalar ve denetimi zaman uyumsuz yöntemi arayan kişiye verir.

ve async anahtar await sözcükleri, ek iş parçacıklarının oluşturulmalarına neden değildir. Zaman uyumsuz yöntem kendi iş parçacığı üzerinde çalışmadığı için zaman uyumsuz yöntemler çoklu iş parçacığı kullanımı gerektirmez. Yöntem geçerli eşitleme kapsamının üzerinde çalışır ve yalnızca yöntem etkin olduğunda iş parçacığındaki zamanı kullanır. CPU'ya bağlı işi bir arka plan iş parçacığına taşımak için kullanabilirsiniz, ancak arka plan iş parçacığı yalnızca sonuçların kullanılabilir olması için bekleyen bir işlemde Task.Run yardımcı olmaz.

Zaman uyumsuz programlamaya zaman uyumsuz yaklaşım, hemen hemen her durumda varolan yaklaşımlara tercih edilir. Kod daha basittir ve yarış durumlarına karşı koruma yapmak zorunda olmadığınız için bu yaklaşım, I/O'ya bağlı işlemler BackgroundWorker için sınıfından daha iyidir. Zaman uyumsuz programlama, kodunuzu çalıştırmayla ilgili koordinasyon ayrıntılarını iş parçacığı havuzuna aktaran iş parçacığından ayırarak zaman uyumsuz programlama yöntemiyle birlikte CPU'ya bağlı işlemlere göre Task.Run BackgroundWorker daha Task.Run iyidir.

async ve await

Bir yöntemin zaman uyumsuz bir yöntem olduğunu, zaman uyumsuz değiştiriciyi kullanarak belirtirsiniz, aşağıdaki iki özelliği etkinleştirirsiniz.

  • İşaretlenen zaman uyumsuz yöntem, askıya alma noktalarının ataması için await kullanabilir. işleci, zaman uyumsuz yöntemin beklenen zaman uyumsuz işlem tamamlandıktan sonra bu noktadan sonra devam await edeceğini derleyiciye söyler. Bu sırada denetim, zaman uyumsuz yönteminin arayanına döner.

    Bir ifadede zaman uyumsuz yöntemin askıya alınması yönteminden çıkış await oluşturmaz finally ve bloklar çalıştırnmaz.

  • İşaretli zaman uyumsuz yöntem, kendisinin çağırdığı yöntemler tarafından bekleniyor olabilir.

Zaman uyumsuz yöntem genellikle bir işlecin bir veya daha fazla oluşumunu içerir, ancak ifadelerin olmaması await await derleyici hatasına neden değildir. Zaman uyumsuz bir yöntem, bir askıya alma noktasını işaretlemek için bir işleç kullanmazsa, yöntemi değiştiriciye rağmen zaman uyumlu bir yöntem olarak await async yürütülür. Derleyici bu tür yöntemler için bir uyarı verir.

async ve await bağlamsal anahtar sözcüklerdir. Daha fazla bilgi ve örnek için aşağıdaki konulara bakın:

Dönüş türleri ve parametreleri

Zaman uyumsuz yöntem genellikle veya Task Task<TResult> döndürür. Zaman uyumsuz bir yöntemin içinde, başka bir zaman uyumsuz yönteme yapılan çağrıdan döndürülen göreve await bir işleç uygulanır.

yöntem Task<TResult> türünde bir işlenen belirten bir deyimi return içeriyorsa dönüş türü olarak TResult belirtin.

Yöntemin dönüş deyimi yoksa veya bir işleneni olmayan bir dönüş deyimi varsa dönüş Task türü olarak kullanın.

C# 7.0'dan başlayarak, türün bir yöntem içeren başka bir dönüş türü de GetAwaiter belirtebilirsiniz. ValueTask<TResult> , böyle bir türe örnektir. System.Threading.Tasks.Extension NuGet kullanılabilir.

Aşağıdaki örnek, bir veya döndüren bir yöntemi nasıl bildir ve Task<TResult> çağırarak Task gösterir:

async Task<int> GetTaskOfTResultAsync()
{
    int hours = 0;
    await Task.Delay(0);

    return hours;
}


Task<int> returnedTaskTResult = GetTaskOfTResultAsync();
int intResult = await returnedTaskTResult;
// Single line
// int intResult = await GetTaskOfTResultAsync();

async Task GetTaskAsync()
{
    await Task.Delay(0);
    // No return statement needed
}

Task returnedTask = GetTaskAsync();
await returnedTask;
// Single line
await GetTaskAsync();

Döndürülmüş her görev, devam eden bir çalışmayı temsil eder. Bir görev, zaman uyumsuz işlemin durumu hakkındaki bilgileri saklar ve sonunda, işlemden alınan nihai sonuca veya başarısız olursa işlemin neden olduğu bir özel duruma ilişkin bilgileri içerir.

Zaman uyumsuz bir yöntemin dönüş türü void de olabilir. Bu dönüş türü öncelikli olarak bir dönüş türünün gerekli olduğu olay void işleyicilerini tanımlamak için kullanılır. Zaman uyumsuz olay işleyicileri, genellikle zaman uyumsuz programlar için başlangıç noktası olarak hizmet eder.

Dönüş türüne sahip zaman uyumsuz bir yöntem beklenmemiştir ve void-returning yönteminin çağıranı yöntemin neden olduğu özel void durumları yakalayamaz.

Zaman uyumsuz yöntem , ref veya out parametrelerinde bildiremaz, ancak yöntemi bu tür parametrelere sahip yöntemleri çağır olabilir. Benzer şekilde, başvuru dönüş değerlerine sahip yöntemleri çağırsa da zaman uyumsuz yöntem başvuruya göre değer getire değildir.

Daha fazla bilgi ve örnekler için bkz. Zaman uyumsuz dönüş türleri (C#). Zaman uyumsuz yöntemlerde özel durumları yakalama hakkında daha fazla bilgi için bkz. try-catch.

Windows Runtime programlamada zaman uyumsuz API'ler aşağıdaki dönüş türlerinden birini içerir ve bunlar görevlere benzer:

Adlandırma kuralı

Kural gereği, yaygın olarak beklenebilir türler (örneğin, , , , ) dönüş yöntemlerinde Task Task<T> ValueTask ValueTask<T> "Async" ile sona eren adlar olması gerekir. Zaman uyumsuz bir işlem başlatan ancak beklenebilir bir türe dönüş yapmayan yöntemlerin adları "Async" ile bitebilir, ancak "Begin", "Start" ile veya bu yöntemin işlem sonucu elde olmadığını önermek için başka bir fiil ile başlayabilir.

Bir olay, taban sınıf veya arabirim sözleşmesi farklı bir ad öneriyorsa kuralı yoksayabilirsiniz. Örneğin, gibi yaygın olay işleyicilerini yeniden adlandırmamanız OnButtonClick gerekir.

Başlık Açıklama Örnek
Async ve await kullanarak birden çok web isteğini paralel yapma (C#) Nasıl aynı anda birkaç görevi başlatacağınızı gösterir. Zaman Uyumsuz Örnek: Birden Çok Web İsteklerini Paralel Yapma
Zaman uyumsuz dönüş türleri (C#) Zaman uyumsuz yöntemlerin ne türler getirtebilirsiniz, gösterir ve her tür uygun olduğunda açıklar.
Sinyal mekanizması olarak iptal belirteci olan görevleri iptal etme. Zaman uyumsuz çözümünüze aşağıdaki işlevin nasıl ekleneceğini gösterir:

- Görev listesini iptal etme (C#)
- Bir süre sonra görevleri iptal etme (C#)
- Zaman uyumsuz görevi tamamlandık şekilde işleme (C#)
Dosya erişimi için zaman uyumsuz kullanma (C#) Dosyalara erişmek için zaman uyumsuz yöntemin ve await işlecinin kullanılmasına ilişkin avantajları listeler ve gösterir.
Görev tabanlı zaman uyumsuz desen (TAP) Zaman uyumsuz bir deseni açıklar, desen ve türlerini Task Task<TResult> temel almaktadır.
Channel 9'da Zaman Uyumsuz Videolar Zaman uyumsuz programlama hakkında çeşitli videoların bağlantılarını sağlar.

Ayrıca bkz.