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ı ve zaman uyumsuz programlamayı 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 uyumsuz yanıt hızını artırır

Zaman uyumsuzluk, web erişimi gibi engelleyici olabilecek etkinlikler için gereklidir. 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 zaman uyumsuz ve await anahtar sözcükleri, zaman uyumsuz programlamanın kalbidir. Bu iki anahtar sözcüğü kullanarak zaman uyumsuz bir yöntem oluşturmak için .NET Framework, .NET Core veya Windows Çalışma Zamanı kaynaklarını kullanarak zaman uyumlu bir yöntem oluşturmak kadar kolay bir yöntem oluşturabilirsiniz. anahtar sözcüğünü kullanarak async tanımladığınız zaman uyumsuz yöntemler, zaman uyumsuz yöntemler olarak adlandırılır.

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

Zaman uyumsuz programlamadan indirilebilen tam bir Windows Presentation Foundation (WPF) örneği bulabilir ve C# dilinde bekleyebilirsiniz.

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

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

    DoIndependentWork();

    string contents = await getStringTask;

    return contents.Length;
}

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

Önceki örnekten çeşitli yöntemler öğrenebilirsiniz. Yöntem imzası ile başlayın. Değiştiriciyi async içerir. Dönüş türü: 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. Başka bir deyişle, görevi yaptığınızda await bir string (contents alırsınız. Görevi beklemeden önce, 'den'e 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 öğesini çağırana GetUrlContentLengthAsyncgeri döner.
  • Denetim tamamlandığında burada getStringTask devam eder.
  • İşleç await daha sonra sonucundan string sonucunu getStringTaskalır.

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

Çağırma GetStringAsync ve 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üne TResultsahip olduğ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 diğer herhangi 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. 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.

.NET Framework'ün önceki sürümlerinde zaman uyumsuz 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 sizi süreç boyunca yönlendirir:

Trace navigation of async control flow

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. Kaynakları engellemekten kaçınmak için, GetStringAsync çağıranı GetUrlContentLengthAsyncolan öğesine denetim verir.

    GetStringAsync bir Task<TResult>döndürür, burada TResult bir dizedir ve GetUrlContentLengthAsync görevi değişkene getStringTask atar. Görev, iş 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 çalışma, 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ş bitti. 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 await işlecini 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 giderleri boşa gider.

    Çağırma yönteminin içinde işleme düzeni devam eder. Çağıran, bu sonucu beklemeden önce sonucuna GetUrlContentLengthAsync bağlı olmayan başka bir iş yapabilir veya arayan hemen bekliyor olabilir. Çağıran yöntem için GetUrlContentLengthAsyncbekliyor ve GetUrlContentLengthAsync 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 'den getStringTaskalır. Atama deyimi, alınan sonucu öğesine contentsatar.

  8. Dize sonucu olduğunda GetUrlContentLengthAsync , yöntemi dizenin uzunluğunu hesaplayabilir. Ardından, öğesinin GetUrlContentLengthAsync çalışması da 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 gibi GetStringAsync yöntemleri nerede bulabileceğinizi merak ediyor olabilirsiniz. .NET Framework 4.5 veya üzeri ve .NET Core, ve awaitile async çalışan 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öntemleri, ve zaman uyumlu yöntemleriyle CopyToReadWritebirlikte iç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 bir yöntemdeki 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ı bir 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 yardımcı olmaz.

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, kodunuzu çalıştırmanın koordinasyon ayrıntılarını iş parçacığı havuzuna Task.Run aktaran Task.Run çalışmadan ayırdığından, zaman uyumsuz programlama yöntemiyle birlikte CPU'ya bağlı işlemlerden daha BackgroundWorker iyidir.

async ve await

Bir yöntemin zaman uyumsuz değiştiriciyi kullanarak 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ı ayarlamak için await kullanabilir. await işleci, derleyiciye, beklenen zaman uyumsuz işlem tamamlanana kadar zaman uyumsuz yöntemin bu noktadan sonra devam etebileceğini söyler. Bu sırada denetim, zaman uyumsuz yönteminin arayanına döner.

    Bir ifadedeki 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, yöntem 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 yöntem genellikle bir Task veya Task<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 dönüş 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 void dönüş türünün gerekli olduğu 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 bir void zaman uyumsuz 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 bir değer döndüremez, ancak başvuru dönüş değerlerine sahip yöntemleri çağırabilir.

Daha fazla bilgi ve örnek için bkz . Zaman uyumsuz dönüş türleri (C#).

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ı

Kural gereği, sık beklenen 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)

Ünvan 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.
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ı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.