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 Async
biter. 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 GetStringAsync
bağlı string
olmayan işler yapabilirsiniz.
operatöre await
çok dikkat edin. Askıya alır GetUrlContentLengthAsync
:
GetUrlContentLengthAsync
tamamlanana kadargetStringTask
devamlenemez.- Bu arada, denetim çağırana
GetUrlContentLengthAsync
döner. - Denetim tamamlandığında burada
getStringTask
devam eder. - İşleç
await
daha sonra sonucu'ndangetStringTask
alı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
TResult
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 başka bir
GetAwaiter
tür.
Daha fazla bilgi için Dönüş türleri ve parametreleri bölümüne bakın.
- Task<TResult> yönteminizde işlenenin türünde
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:
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.
Çağıran yöntem, zaman uyumsuz yöntemi çağırır ve bekler
GetUrlContentLengthAsync
.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 .İ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ı olanGetUrlContentLengthAsync
öğesine verir.GetStringAsync
bir Task<TResult>döndürür, buradaTResult
bir dizedir veGetUrlContentLengthAsync
görevi değişkenegetStringTask
atar. Görev, çalışmaGetStringAsync
tamamlandığında gerçek bir dize değeri üretme taahhüdüyle çağrısı için devam eden işlemi temsil eder.getStringTask
Henüz beklenmadığı için,GetUrlContentLengthAsync
sonucuna bağlıGetStringAsync
olmayan diğer çalışmalarla devam edebilir. Bu iş, zaman uyumlu yöntemineDoIndependentWork
yapılan bir çağrı ile temsil edilir.DoIndependentWork
, işini yapıp çağırana geri dönen zaman uyumlu bir yöntemdir.GetUrlContentLengthAsync
, sonucundan bir sonuçgetStringTask
almadan 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ıGetUrlContentLengthAsync
yönteme denetim vermek için bir await işleci kullanır.GetUrlContentLengthAsync
çağırana birTask<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 nedenlegetStringTask
) tamamlanmadan önceGetUrlContentLengthAsync
tamamlanırsa, denetim içindeGetUrlContentLengthAsync
kalır. Çağrılan zaman uyumsuz işlemgetStringTask
zaten tamamlandıysa ve nihai sonucu beklemek zorunda değilse, askıya alma veGetUrlContentLengthAsync
sonra geri dönmeGetUrlContentLengthAsync
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çinGetUrlContentLengthAsync
bekliyor veGetUrlContentLengthAsync
öğesini bekliyorGetStringAsync
.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önteminingetStringTask
tamamlanmasını temsil eden görevde depolanır. await işleci sonucu'ndangetStringTask
alır. Atama deyimi, alınan sonucu öğesinecontents
atar.Dize sonucu olduğunda
GetUrlContentLengthAsync
, yöntemi dizenin uzunluğunu hesaplayabilir. Ardından da işiGetUrlContentLengthAsync
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 vefinally
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ü TResult
olarak 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:
- IAsyncOperation<TResult>öğesine karşılık gelen Task<TResult>
- IAsyncActionöğesine karşılık gelen Task
- IAsyncActionWithProgress<TProgress>
- IAsyncOperationWithProgress<TResult,TProgress>
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 OnButtonClick
yaygı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. |