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()
{
using 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 Async
biter. 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 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 öğesini çağırana
GetUrlContentLengthAsync
geri döner. - Denetim tamamlandığında burada
getStringTask
devam eder. - İşleç
await
daha sonra sonucundanstring
sonucunugetStringTask
alı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
TResult
sahip 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.
- Task<TResult> yönteminizde işlenenin türüne
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:
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. Kaynakları engellemekten kaçınmak için,GetStringAsync
çağıranıGetUrlContentLengthAsync
olan öğesine denetim verir.GetStringAsync
bir Task<TResult>döndürür, buradaTResult
bir dizedir veGetUrlContentLengthAsync
görevi değişkenegetStringTask
atar. Görev, işGetStringAsync
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 çalışma, 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ş 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ıGetUrlContentLengthAsync
yönteme denetim vermek için await işlecini 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
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çinGetUrlContentLengthAsync
bekliyor veGetUrlContentLengthAsync
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 'dengetStringTask
alır. Atama deyimi, alınan sonucu öğesinecontents
atar.Dize sonucu olduğunda
GetUrlContentLengthAsync
, yöntemi dizenin uzunluğunu hesaplayabilir. Ardından, öğesininGetUrlContentLengthAsync
ç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 await
ile 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 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, 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ü TResult
olarak 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:
- IAsyncOperation<TResult>öğesine karşılık gelir Task<TResult>
- IAsyncActionöğesine karşılık gelir Task
- IAsyncActionWithProgress<TProgress>
- IAsyncOperationWithProgress<TResult,TProgress>
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 OnButtonClick
yaygı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. |