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#, .NET çalışma zamanında zaman uyumsuz destek kullanan basitleştirilmiş yaklaşımı ( zaman uyumsuz programlama) destekler. 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ı artırır

Zaman uyumsuzluk, web erişimi gibi engelleyici olabilecek etkinlikler için önemlidir. Web kaynağına erişim bazen yavaş veya gecikmeli olabilir. Böyle bir etkinlik zaman uyumlu bir işlemde engellenirse, uygulamanın tamamının beklemesi gerekir. 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'ten ve Windows Çalışma Zamanı listelenen API'ler zaman uyumsuz programlamayı destekleyen yöntemler içerir.

Uygulama alanı Zaman uyumsuz yöntemlerle .NET türleri Zaman uyumsuz yöntemlerle türleri Windows Çalışma Zamanı
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 kalbidir. Bu iki anahtar sözcüğü kullanarak .NET Framework, .NET Core veya Windows Çalışma Zamanı kaynakları kullanarak zaman uyumlu bir yöntem oluşturabildiğiniz kadar kolay bir zaman uyumsuz yöntem oluşturabilirsiniz. anahtar sözcüğünü kullanarak async tanımladığınız zaman uyumsuz yöntemlere zaman uyumsuz yöntemler denir.

Aşağıdaki örnekte zaman uyumsuz bir yöntem gösterilmektedir. Koddaki neredeyse her şey size tanıdık gelmelidir.

C# dilinde zaman uyumsuz ve await ile Zaman Uyumsuz programlamadan indirilebilen tam bir Windows Presentation Foundation (WPF) örneği 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 öğrenebilirsiniz. Yöntem imzası ile başlayın. Değiştiriciyi async içerir. Dönüş türü şöyledir Task<int> (daha fazla seçenek için "Dönüş Türleri" bölümüne bakın). Yöntem adı ile Asyncbiter. yönteminin GetStringAsync gövdesinde bir Task<string>döndürür. Bu, görevi aldığınızda await bir string (contents elde ettiğiniz anlamına gelir. Görevi beklemeden önce, 'den'ine GetStringAsyncbağlı string olmayan işler yapabilirsiniz.

operatöre await çok dikkat edin. Askıya alır GetUrlContentLengthAsync:

  • GetUrlContentLengthAsync tamamlanana kadar getStringTask devamlenemez.
  • Bu arada, denetim çağırana GetUrlContentLengthAsyncdöner.
  • Denetim tamamlandığında burada getStringTask devam eder.
  • İşleç await daha sonra sonucu'ndan getStringTaskalırstring.

return deyimi bir tamsayı sonucu belirtir. Bekleyen GetUrlContentLengthAsync tüm yöntemler uzunluk değerini alır.

Çağırma GetStringAsync ile tamamlanmasını bekleme arasında gerçekleştirebileceği bir çalışma yoksaGetUrlContentLengthAsync, aşağıdaki tek deyimde çağırarak ve bekleyerek kodunuzu basitleştirebilirsiniz.

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

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

  • Yöntem imzası bir async değiştirici 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önteminizde işlenenin türünde TResultolduğu bir dönüş deyimi varsa.
    • Task yönteminizin return deyimi yoksa veya işleneni olmayan bir return deyimi varsa.
    • void zaman uyumsuz bir olay işleyicisi yazıyorsanız.
    • Yöntemi olan başka bir GetAwaiter tür.

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

  • Yöntemi genellikle en az bir await ifade içerir ve bu ifade, beklenen zaman uyumsuz işlem tamamlanana kadar yöntemin devam edebildiği bir noktayı 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 .NET Framework sürümlerindeki zaman uyumsuzluk hakkında daha fazla bilgi için bkz. TPL ve geleneksel .NET Framework zaman uyumsuz 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 diyagram işlemde size yol açar:

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

Diyagramdaki sayılar, çağıran bir yöntem zaman uyumsuz yöntemi çağırdığında başlatılan aşağıdaki adımlara karşılık gelir.

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

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

  3. İlerleme durumunu askıya alan bir şey olur GetStringAsync . Bir web sitesinin indirmesini veya başka bir engelleyen etkinliği beklemesi gerekebilir. Engelleyici kaynakları önlemek için, GetStringAsync denetimi çağıranı olan GetUrlContentLengthAsyncöğesine verir.

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

  4. getStringTask Henüz beklenmadığı için, GetUrlContentLengthAsync sonucuna bağlı GetStringAsyncolmayan diğer çalışmalarla devam edebilir. Bu iş, zaman uyumlu yöntemine DoIndependentWorkyapılan bir çağrı ile temsil edilir.

  5. DoIndependentWork , işini yapıp çağırana geri dönen zaman uyumlu bir yöntemdir.

  6. GetUrlContentLengthAsync , sonucundan bir sonuç getStringTaskalmadan gerçekleştirebileceği iş dışıdır. GetUrlContentLengthAsync next, indirilen dizenin uzunluğunu hesaplamak ve döndürmek ister, ancak yöntem dizeye sahip olana kadar bu değeri hesaplayamaz.

    Bu nedenle, GetUrlContentLengthAsync ilerleme durumunu askıya almak ve adlı GetUrlContentLengthAsyncyönteme denetim vermek için bir await işleci kullanır. GetUrlContentLengthAsync çağırana bir Task<int> döndürür. Görev, indirilen dizenin uzunluğu olan bir tamsayı sonucu verecek bir taahhüdü temsil eder.

    Not

    GetStringAsync (ve bu nedenle getStringTask) tamamlanmadan önce GetUrlContentLengthAsync tamamlanırsa, denetim içinde GetUrlContentLengthAsynckalır. Çağrılan zaman uyumsuz işlem getStringTask zaten tamamlandıysa ve nihai sonucu beklemek zorunda değilse, askıya alma ve GetUrlContentLengthAsync sonra geri dönme GetUrlContentLengthAsync gideri boşa gider.

    Çağırma yönteminin içinde işleme düzeni devam eder. Çağıran, sonucu beklemeden GetUrlContentLengthAsync önce sonucuna bağlı olmayan başka işler de yapabilir veya çağıran hemen bekler. Çağıran yöntem için GetUrlContentLengthAsyncbekliyor ve GetUrlContentLengthAsync öğesini bekliyor GetStringAsync.

  7. GetStringAsync tamamlar ve bir dize sonucu üretir. Dize sonucu, çağrısı GetStringAsync tarafından beklediğiniz şekilde döndürülmüyor. (Yöntemin 3. adımda zaten bir görev döndürdüğünü unutmayın.) Bunun yerine, dize sonucu yönteminin getStringTasktamamlanmasını temsil eden görevde depolanır. await işleci sonucu'ndan getStringTaskalır. Atama deyimi, alınan sonucu öğesine contentsatar.

  8. Dize sonucu olduğunda GetUrlContentLengthAsync , yöntemi dizenin uzunluğunu hesaplayabilir. Ardından da işi 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öntemlere GetStringAsync nereden ulaşabileceğinizi merak ediyor olabilirsiniz. .NET Framework 4.5 veya üzeri ve .NET Core ile awaitçalışan async birçok üye içerir. Bunları üye adına eklenen "Zaman Uyumsuz" soneki ve veya dönüş türüne TaskTask<TResult>göre tanıyabilirsiniz. Örneğin, System.IO.Stream sınıfı , ReadAsyncve WriteAsync gibi CopyToAsyncyöntemlerin yanı sıra , Readve Writezaman uyumlu yöntemleri CopyToiçerir.

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

İş Parçacıkları

Zaman uyumsuz yöntemlerin engelleyici olmayan işlemler olmaları amaçlanmıştır. await Zaman uyumsuz yöntemdeki 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.

async ve await anahtar sözcükleri ek iş parçacıklarının oluşturulmasına neden olmaz. 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ı çalışmayı arka plan iş parçacığına taşımak için kullanabilirsiniz Task.Run , ancak arka plan iş parçacığı yalnızca sonuçların kullanılabilir olmasını bekleyen bir işlemde işe yaramaz.

Zaman uyumsuz programlamaya zaman uyumsuz yaklaşım, hemen hemen her durumda varolan yaklaşımlara tercih edilir. Kod daha basit olduğundan ve yarış koşullarına BackgroundWorker karşı korumanız gerekmeyen bu yaklaşım özellikle G/Ç'ye bağlı işlemler için sınıfından daha iyidir. Zaman uyumsuz programlama, yöntemiyle birlikte Task.Run CPU'ya bağlı işlemlerden daha BackgroundWorker iyidir çünkü zaman uyumsuz programlama kodunuzu çalıştırmanın koordinasyon ayrıntılarını iş parçacığı havuzuna aktaran Task.Run çalışmadan ayırır.

async ve await

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

  • İşaretli zaman uyumsuz yöntem, askıya alma noktalarını belirlemede await kullanabilir. await işleci derleyiciye, zaman uyumsuz yöntemin beklenen zaman uyumsuz işlem tamamlanana kadar bu noktadan sonra devam eteebileceğini söyler. Bu sırada denetim, zaman uyumsuz yönteminin arayanına döner.

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

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

Zaman uyumsuz yöntem genellikle bir işlecin bir await veya daha fazla örneğini içerir, ancak ifadelerin await olmaması derleyici hatasına neden olmaz. Zaman uyumsuz bir yöntem bir askıya alma noktasını işaretlemek için işleç await kullanmıyorsa, değiştiriciye rağmen async zaman uyumlu bir yöntem olarak 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 bir yöntem genellikle veya TaskTask<TResult>döndürür. Zaman uyumsuz bir yöntemin içinde, başka bir await zaman uyumsuz yönteme yapılan çağrıdan döndürülen bir göreve bir işleç uygulanır.

yöntemi türünde bir işlenen belirten bir return deyim içeriyorsa dönüş türü TResultolarak belirtirsinizTask<TResult>.

Yöntemin return deyimi yoksa veya işlenen döndürmeyen bir return deyimi varsa dönüş türü olarak kullanırsınız Task .

Türün bir yöntem içermesi koşuluyla başka bir GetAwaiter dönüş türü de belirtebilirsiniz. ValueTask<TResult> bu tür bir örnektir. System.Threading.Tasks.Extension NuGet paketinde kullanılabilir.

Aşağıdaki örnekte, veya Taskdöndüren Task<TResult> bir yöntemi nasıl bildirdiğiniz ve çağırdığınız gösterilmektedir:

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 void dönüş türü de olabilir. Bu dönüş türü öncelikle bir dönüş türünün gerekli olduğu void olay 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 void yöntem beklenemez ve void-return yöntemini çağıran, yöntemin attığı özel durumları yakalayamaz.

Zaman uyumsuz bir yöntem in, ref veya out parametrelerini bildiremez, ancak yöntemi bu tür parametrelere sahip yöntemleri çağırabilir. Benzer şekilde, zaman uyumsuz bir yöntem başvuruya göre değer döndüremez, ancak ref dönüş değerlerine sahip yöntemleri çağırabilir.

Daha fazla bilgi ve örnek 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 Çalışma Zamanı programlamadaki zaman uyumsuz API'ler, görevlere benzer şekilde aşağıdaki dönüş türlerinden birine sahiptir:

Adlandırma kuralı

Kurala göre, yaygın olarak beklenebilir türler döndüren yöntemlerin (örneğin, Task, Task<T>, ValueTask, ValueTask<T>) "Async" ile biten adları olmalıdır. Zaman uyumsuz bir işlem başlatan ancak beklenebilir bir tür döndürmeyen yöntemlerin adları "Async" ile bitmemelidir, ancak "Begin", "Start" veya bu yöntemi önermek için başka bir fiil ile başlayıp işlemin sonucunu döndürmez veya oluşturmaz.

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

İlgili makaleler (Visual Studio)

Başlık Açıklama
Async ve await kullanarak birden çok web isteğini paralel olarak yapma (C#) Nasıl aynı anda birkaç görevi başlatacağınızı gösterir.
Zaman uyumsuz dönüş türleri (C#) Zaman uyumsuz yöntemlerin döndürebileceği türleri gösterir ve her türün ne zaman uygun olduğunu açıklar.
bir sinyal mekanizması olarak iptal belirteci ile 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#)
- Belirli bir süre sonra görevleri iptal etme (C#)
- Zaman uyumsuz görevi tamamlandıklarında 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 Task<TResult> türlerini temel alırTask.
Kanal 9'da Zaman Uyumsuz Videolar Zaman uyumsuz programlama hakkında çeşitli videoların bağlantılarını sağlar.

Ayrıca bkz.