it-swarm-tr.com

"Eşzamansız" ve nasıl kullanılır?

Anladığım kadarıyla, async VE await / 'nın kod yazmasını ve okumasını kolaylaştıracak ana şeylerden biri, fakat uzun süreli mantık yapmak için bunları arka plandaki iş parçacıklarına eşit kullanmak mı?

Şu anda en temel örneği deniyorum. Satır içi bazı yorumlar ekledim. Bunu benim için açıklayabilir misin?

// I don't understand why this method must be marked as `async`.
private async void button1_Click(object sender, EventArgs e)
{
    Task<int> access = DoSomethingAsync();
    // task independent stuff here

    // this line is reached after the 5 seconds sleep from 
    // DoSomethingAsync() method. Shouldn't it be reached immediately? 
    int a = 1; 

    // from my understanding the waiting should be done here.
    int x = await access; 
}

async Task<int> DoSomethingAsync()
{
    // is this executed on a background thread?
    System.Threading.Thread.Sleep(5000);
    return 1;
}
830
Dan Dinu

async ve await kullanıldığında, derleyici arka planda bir durum makinesi oluşturur.

İşte devam eden bazı üst düzey detayları açıklayabileceğimi umduğum bir örnek: 

public async Task MyMethodAsync()
{
    Task<int> longRunningTask = LongRunningOperationAsync();
    // independent work which doesn't need the result of LongRunningOperationAsync can be done here

    //and now we call await on the task 
    int result = await longRunningTask;
    //use the result 
    Console.WriteLine(result);
}

public async Task<int> LongRunningOperationAsync() // assume we return an int from this long running operation 
{
    await Task.Delay(1000); // 1 second delay
    return 1;
}

Tamam, peki burada ne olur:

  1. Task<int> longRunningTask = LongRunningOperationAsync();, LongRunningOperation uygulamasını çalıştırmaya başlar.

  2. Bağımsız iş başlayalım, ana iş parçacığını (iş parçacığı ID = 1) varsayalım sonra await longRunningTask ulaşıldı. 

    Şimdi, longRunningTask bitmediyse ve hala çalışıyorsa, MyMethodAsync() çağrı yöntemine geri döner, böylece ana iş parçacığı engellenmez. longRunningTask işlemi tamamlandığında, ThreadPool'dan bir konu (herhangi bir konu olabilir) önceki bağlamında MyMethodAsync() işlevine dönecek ve çalışmaya devam edecektir (bu durumda konsola yazdırma). 

İkinci bir durum longRunningTask uygulamasının çalışmasını zaten bitirmiş olması ve sonucun mevcut olmasıdır. await longRunningTask 'a ulaşırken, zaten sonucumuz var, böylece kod aynı iş parçacığında çalışmaya devam edecek. (bu durumda baskı sonucu konsola gönderilir). Elbette bu, bir Task.Delay(1000) işlevinin dahil olduğu yukarıdaki örnek için durum böyle değil. 

629
Dan Dinu

Diğer cevaplara ek olarak bekliyor (C # Referans)

ve daha spesifik olarak içerilen örnekte durumunuzu biraz açıklar

Aşağıdaki Windows Forms örneği, bir .__ 'da beklemenin kullanımını göstermektedir. zaman uyumsuz yöntem, WaitAsynosouslyAsync. Bunun davranışını zıt yapın. WaitSynchronously davranışını gösteren yöntem. Beklemeden Bir göreve uygulanan operatör, WaitSynchronously senkronize olarak çalışır. tanımında async değiştiricinin kullanımına rağmen ve bir çağrıya. Konu. Vücudunda uyu.

private async void button1_Click(object sender, EventArgs e)
{
    // Call the method that runs asynchronously.
    string result = await WaitAsynchronouslyAsync();

    // Call the method that runs synchronously.
    //string result = await WaitSynchronously ();

    // Display the result.
    textBox1.Text += result;
}

// The following method runs asynchronously. The UI thread is not
// blocked during the delay. You can move or resize the Form1 window 
// while Task.Delay is running.
public async Task<string> WaitAsynchronouslyAsync()
{
    await Task.Delay(10000);
    return "Finished";
}

// The following method runs synchronously, despite the use of async.
// You cannot move or resize the Form1 window while Thread.Sleep
// is running because the UI thread is blocked.
public async Task<string> WaitSynchronously()
{
    // Add a using directive for System.Threading.
    Thread.Sleep(10000);
    return "Finished";
}
142
Adriaan Stander

Anlayışıma göre, zaman uyumsuzluğunun ve beklediği en önemli şeylerden biri, kodun yazılmasını ve okunmasını kolaylaştırmaktır.

Evet, asenkron kodunu yazmayı ve okumayı kolaylaştırıyorlar.

Uzun süreli mantık gerçekleştirmek için arka plan iplikleri yumurtlama ile aynı şey midir?

Bir şey değil.

// neden bu yöntemin "asenkron" olarak işaretlenmesi gerektiğini anlamadım.

async anahtar sözcüğü, await anahtar sözcüğünü etkinleştirir. Bu yüzden await kullanan herhangi bir yöntem async olarak işaretlenmelidir.

// bu satıra DoSomethingAsync () yönteminden 5 saniye uyuduktan sonra ulaşılır. Derhal ulaşılmalı mı? 

Hayır, çünkü async yöntemleri varsayılan olarak başka bir iş parçacığında çalıştırılmaz.

// bu bir arka plan iş parçacığında yürütülür?

Yok hayır.


async/await intro 'ı bulabilirsiniz. Resmi MSDN dökümanları ayrıca alışılmadık derecede iyidir (özellikle TAP bölüm) ve async ekibi mükemmel bir SSS çıkardı.

122
Stephen Cleary

Açıklama

İşte yüksek düzeyde bir async/beklemenin hızlı bir örneği. Bunun ötesinde göz önünde bulundurulması gereken daha fazla ayrıntı var.

Not: Task.Delay(1000), 1 saniye boyunca çalışmayı simüle eder. Bunu, harici bir kaynaktan yanıt beklemek olarak düşünmenin en iyisi olduğunu düşünüyorum. Kodumuz cevap beklediğinden, sistem çalışan görevi bir kenara atabilir ve bittiğinde tekrar geri gelebilir. Bu arada, bu konu üzerinde başka bir iş yapabilir.

Aşağıdaki örnekte, ilk blok tam olarak bunu yapıyor. Tüm görevleri hemen başlatır (Task.Delay satırları) ve bunları kenara ayırır. Kod, bir sonraki satıra geçmeden önce 1 saniye gecikme gerçekleşene kadar await a satırında duraklar. b, c, d ve e __ 'ın tümü, a ile hemen hemen aynı anda (beklemedeki eksiklik nedeniyle) çalışmaya başladığı için, bu durumda kabaca aynı anda bitirmeleri gerekir.

Aşağıdaki örnekte, second bloğu bir göreve başlamakta ve bir sonraki göreve başlamadan önce bitirmesini beklemektedir (bu await ne yapar). Bunun her tekrarı 1 saniye sürer. await programı duraklatıyor ve devam etmeden önce sonucu bekliyor. Birinci ve ikinci bloklar arasındaki temel fark budur.

Örnek

Console.WriteLine(DateTime.Now);

// This block takes 1 second to run because all
// 5 tasks are running simultaneously
{
    var a = Task.Delay(1000);
    var b = Task.Delay(1000);
    var c = Task.Delay(1000);
    var d = Task.Delay(1000);
    var e = Task.Delay(1000);

    await a;
    await b;
    await c;
    await d;
    await e;
}

Console.WriteLine(DateTime.Now);

// This block takes 5 seconds to run because each "await"
// pauses the code until the task finishes
{
    await Task.Delay(1000);
    await Task.Delay(1000);
    await Task.Delay(1000);
    await Task.Delay(1000);
    await Task.Delay(1000);
}
Console.WriteLine(DateTime.Now);

ÇIKTI:

5/24/2017 2:22:50 PM
5/24/2017 2:22:51 PM (First block took 1 second)
5/24/2017 2:22:56 PM (Second block took 5 seconds)

SynchronizationContext ile ilgili ek bilgi

Not: Burası benim için biraz sislendiği bir yer, bu yüzden herhangi bir konuda yanılmıyorsam, lütfen beni düzeltin ve cevabı güncelleyeceğim. Bunun nasıl çalıştığına dair temel bir anlayışa sahip olmak önemlidir; ancak, ConfigureAwait(false) işlevini asla kullanmadığınız sürece, uzman olmadan, bu konuda uzmanlaşmadan geçebilirsiniz, ancak optimizasyon için bir fırsattan kaçınma ihtimaliniz olduğunu varsayalım.

Bunun async/await kavramını kavraması biraz daha zorlaştıran bir yönü var. Bu örnekte, bunların hepsi aynı iş parçacığında oluyor (ya da en azından SynchronizationContext ile ilgili olarak aynı iş parçacığı olarak görünüyor). Varsayılan olarak, await, üzerinde çalıştığı orijinal iş parçacığının eşitleme bağlamını geri yükler. Örneğin, ASP.NET'te, bir istek geldiğinde bir dizeye bağlı olan bir HttpContext'e sahip olursunuz. Bu içerik, dil, IP adresi, başlıklar gibi orijinal İstek nesnesi gibi orijinal Http isteğine özgü şeyler içerir. Bir şeyleri işleyerek yarıda konu değiştirirseniz, felaket olabilecek farklı bir HttpContext'te bu nesneden bilgi almaya çalışmanız olası olabilir. İçeriği hiçbir şey için kullanmayacağınızı biliyorsanız, onunla "ilgilenmemeyi" seçebilirsiniz. Bu, temel olarak kodunuzu, bağlamı beraberinde getirmeden ayrı bir iş parçacığında çalıştırmanıza izin verir.

Bunu nasıl başardın? Varsayılan olarak, await a; kodu aslında bağlamı yakalamak ve geri yüklemek istediğinizi varsayıyor:

await a; //Same as the line below
await a.ConfigureAwait(true);

Ana kodun, orijinal bağlam olmadan yeni bir iş parçacığında devam etmesine izin vermek istiyorsanız, sadece true yerine false komutunu kullanırsınız, böylece içeriği geri yüklemesi gerekmediğini bilir.

await a.ConfigureAwait(false);

Program duraklatıldıktan sonra, tamamen farklı bir bağlamda tamamen farklı bir konu üzerinde potansiyel olarak devam edecektir. Performans iyileştirmenin geleceği yer burasıdır - başlangıçtaki orijinal içeriği geri yüklemek zorunda kalmadan mevcut herhangi bir iş parçacığında devam edebilir.

Bu şeyler kafa karıştırıcı mı? Cehennem evet! Çözebilir misin? Muhtemelen! Kavramları bir kez anladıktan sonra, zaten Stephen Asyn'in teknik bir async/bekliyor anlayışı olan birine karşı daha fazla teçhizatlı açıklamalarına geçin.

116
Joe Phillips

Yukarıdaki açıklamaları basit bir konsol programında çalışırken gösterme -

class Program
{
    static void Main(string[] args)
    {
        TestAsyncAwaitMethods();
        Console.WriteLine("Press any key to exit...");
        Console.ReadLine();
    }

    public async static void TestAsyncAwaitMethods()
    {
        await LongRunningMethod();
    }

    public static async Task<int> LongRunningMethod()
    {
        Console.WriteLine("Starting Long Running method...");
        await Task.Delay(5000);
        Console.WriteLine("End Long Running method...");
        return 1;
    }
}

Ve çıktı:

Starting Long Running method...
Press any key to exit...
End Long Running method...

Böylece,

  1. Ana uzun çalışma yöntemini TestAsyncAwaitMethods üzerinden başlatır. Bu, o anki diziyi durdurmadan hemen döner ve hemen 'Çıkmak için herhangi bir tuşa basın' mesajını görürüz
  2. Bütün bunlar, LongRunningMethod arka planda çalışıyor. Tamamlandığında, Threadpool'dan başka bir konu bu içeriği alır ve son mesajı görüntüler.

Böylece, iplik değil engellenir. 

47
sppc42

Bence System.Threading.Thread.Sleep ile kötü bir örnek seçtiniz.

async işlevinin amacı, DownloadFileAsync işlevi gibi ana iş parçacığını kilitlemeden arka planda yürütmesine izin vermektir.

System.Threading.Thread.Sleep “yapılan” bir şey değildir, sadece uyur ve bu nedenle bir sonraki satıra 5 saniye sonra ulaşılır ...

Bu makaleyi okuyun, bence async ve await kavramının harika bir açıklaması: http://msdn.Microsoft.com/en-us/library/vstudio/hh191443.aspx

38
Vnuk

İşte takip edenlere netleştirmek için hızlı bir konsol programı. "TaskToDo" yöntemi, zaman uyumsuz yapmak istediğiniz uzun süre çalışan yönteminizdir. Bunu yapmak Async'i TestAsync yöntemi ile yapılır. Test döngüler yöntemi, yalnızca "TaskToDo" görevleriyle çalışır ve bunları Async'te çalıştırır. Bunu sonuçlarda görebilirsiniz çünkü aynı sırayla koşmadan koşuya tamamlanmazlar - tamamlandığında konsol UI iş parçacığına rapor verirler. Basit, ama basit örneklerin modelin çekirdeğini daha fazla ilgili örneklerden daha iyi ortaya çıkardığını düşünüyorum:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace TestingAsync
{
    class Program
    {
        static void Main(string[] args)
        {
            TestLoops();
            Console.Read();
        }

        private static async void TestLoops()
        {
            for (int i = 0; i < 100; i++)
            {
                await TestAsync(i);
            }
        }

        private static Task TestAsync(int i)
        {
            return Task.Run(() => TaskToDo(i));
        }

        private async static void TaskToDo(int i)
        {
            await Task.Delay(10);
            Console.WriteLine(i);
        }
    }
}
17
MarkWalls

Bu cevap ASP.NET'e özgü bazı bilgiler vermeyi amaçlamaktadır.

MVC kontrol ünitesinde async/bekliyor kullanıldığında, aşağıdaki maddede açıklandığı gibi, iplik havuzu kullanımını artırmak ve daha iyi bir verim elde etmek mümkündür.

http://www.asp.net/mvc/tutorials/mvc-4/using-asynchronous-methods-in-aspnet-mvc-4

Çok sayıda eşzamanlı istek gören web uygulamalarında, start-up veya patlamış bir yük var (eşzamanlılığın aniden arttığı yerlerde), Bu web servis aramalarını asenkronize etmek, başvurunuzun yanıt verebilirliği. Zaman uyumsuz bir istek senkronize bir istek olarak işlemek için aynı süre. Örneğin, Bir istek için iki saniye gerektiren bir web servis çağrısı yaparsa. tamamlandığında, istek gerçekleştirilip gerçekleştirilmediği iki saniye sürer. senkronize veya senkronize olmayan Ancak, zaman uyumsuz bir arama sırasında, bir iş parçacığının, diğer isteklere yanıt vermesi engellenmez. ilk isteğin tamamlanmasını bekler. Bu nedenle, zaman uyumsuz istekler istek sırasını engeller ve mevcut olduğunda havuz büyümesini hızlandırır. uzun süren işlemleri başlatan birçok eşzamanlı istek.

11
Lex Li

Buradaki tüm cevaplar Task.Delay () veya başka bir zaman uyumsuz işlev kullanır. Ama işte bu benim async fonksiyonlarından hiçbirini kullanmayan bir örnek:

    // Starts counting to a large numbewr and then immediately displays message "i'm counting...". 
    // Then it waits for task to finish and displays "finished, press any key".
    static void asyncTest ()
    {
        Console.WriteLine("Started asyncTest()");
        Task<long> task = asyncTest_count();
        Console.WriteLine("Started counting, please wait...");
        task.Wait(); // if you comment this line you will see that message "Finished counting" will be displayed before we actually finished counting.
        //Console.WriteLine("Finished counting to " + task.Result.ToString()); // using task.Result seems to also call task.Wait().
        Console.WriteLine("Finished counting.");
        Console.WriteLine("Press any key to exit program.");
        Console.ReadLine();
    }

    static async Task<long> asyncTest_count()
    {
        long k = 0;
        Console.WriteLine("Started asyncTest_count()");
        await Task.Run(() =>
        {
            long countTo = 100000000;
            int prevPercentDone = -1;
            for (long i = 0; i <= countTo; i++)
            {
                int percentDone = (int)(100 * (i / (double)countTo));
                if (percentDone != prevPercentDone)
                {
                    prevPercentDone = percentDone;
                    Console.Write(percentDone.ToString() + "% ");
                }

                k = i;
            }
        });
        Console.WriteLine("");
        Console.WriteLine("Finished asyncTest_count()");
        return k;
    }
10
Tone Škoda

Dürüst olmak gerekirse, hala en iyi açıklamanın gelecekle ilgili olduğunu düşünüyorum ve Wikipedia'da vaat etti: http://en.wikipedia.org/wiki/Futures_and_promises

Temel fikir, görevleri eşzamansız yürüten ayrı bir iş parçacığı havuzunuz olmasıdır. Kullanırken. Bununla birlikte, nesne işlemi bir süre içinde yürüteceğine dair söz verir ve talep ettiğinizde size sonuç verir. Bu, sonucu istediğinizde ve tamamlamadığınızda engelleyeceği, ancak iş parçacığı havuzunda yürütüldüğü anlamına gelir.

Oradan işleri optimize edebilirsiniz: bazı işlemler zaman uyumsuz olarak uygulanabilir ve dosya IO ve ağ iletişimi gibi şeyleri sonraki istekleri bir araya toplayarak ve/veya yeniden sıralayarak optimize edebilirsiniz. Bu zaten Microsoft'un görev çerçevesinde olup olmadığından emin değilim - ancak bu değilse ekleyeceğim ilk şeylerden biri olurdu.

Gelecekteki örüntüsünü C # 4.0'da verim ile gerçekte uygulayabilirsiniz. Tam olarak nasıl çalıştığını bilmek istiyorsanız, iyi bir iş yapan bu bağlantıyı önerebilirim: http://code.google.com/p/fracture/source/browse/trunk/Squared/TaskLib/ . Bununla birlikte, kendinizle oynamaya başlarsanız, tüm harika şeyleri yapmak istiyorsanız gerçekten dil desteğine ihtiyacınız olduğunu fark edeceksiniz - ki bu tam olarak Microsoft'un yaptığı gibi.

9
atlaste

Bu kemana bakın https://dotnetfiddle.net/VhZdL (ve mümkünse onu geliştirin) çalıştırmak için basit konsol uygulaması = ki aynı programda Task, Task.WaitAll (), async ve bekliyor operatörlerinin kullanımlarını gösterir.

Bu keman yürütme döngüsü konseptinizi temizlemelidir.

İşte örnek kod

using System;
using System.Threading.Tasks;

public class Program
{
    public static void Main()
    {               
        var a = MyMethodAsync(); //Task started for Execution and immediately goes to Line 19 of the code. Cursor will come back as soon as await operator is met       
        Console.WriteLine("Cursor Moved to Next Line Without Waiting for MyMethodAsync() completion");
        Console.WriteLine("Now Waiting for Task to be Finished");       
        Task.WaitAll(a); //Now Waiting      
        Console.WriteLine("Exiting CommandLine");       
    }

    public static async Task MyMethodAsync()
    {
        Task<int> longRunningTask = LongRunningOperation();
        // independent work which doesn't need the result of LongRunningOperationAsync can be done here
        Console.WriteLine("Independent Works of now executes in MyMethodAsync()");
        //and now we call await on the task 
        int result = await longRunningTask;
        //use the result 
        Console.WriteLine("Result of LongRunningOperation() is " + result);
    }

    public static async Task<int> LongRunningOperation() // assume we return an int from this long running operation 
    {
        Console.WriteLine("LongRunningOperation() Started");
        await Task.Delay(2000); // 2 second delay
        Console.WriteLine("LongRunningOperation() Finished after 2 Seconds");
        return 1;
    }   

}

Çıktı Penceresinden gelen izleme: enter image description here

7
vibs2006

En hızlı öğrenme için ..

  • Metot yürütme akışını anlama (şema ile): 3 dakika

  • Soru yönlendirme (öğrenme aşkına): 1 dak

  • Çabuk sözdizimi şekeri ile almak: 5 dakika

  • Bir geliştiricinin kafasını karıştırın: 5 dak

  • Sorun: Gerçek dünyadaki normal kodun uygulanmasını hızlı bir şekilde Async kodu olarak değiştirin: 2 dakika

  • Nereye İleri?

Yöntem yürütme akışını anlama (şema ile): 3 dakika

Bu resimde, sadece # 6 enter image description here

6 numaralı adımda: AccessTheWebAsync (), getStringTask sonucundan kaynaklanamayacak kadar işini bitirdi. Bu nedenle, AccessTheWebAsync, ilerlemesini askıya almak ve arayan kişiye kontrolü (verim) geri vermek için bir bekleyen operatör kullanır. AccessTheWebAsync arayana bir Görev (dize dönüş değeri) döndürür. Görev, bir dize sonucu üretme sözünü temsil ediyor. Peki çağrı ne zaman dönecek? tekrar 2. çağrı?

AccessTheWebAsync () 'nin arayanı beklemekten başka bir şey yapmadı (bazı iç görevler yapmış olabilir ve gerekirse bekledi). Böylece arayanlar AccessTheWebAsync'i bekliyor ve AccessTheWebAsync şu anda GetStringAsync'i bekliyor.

Unutmayın, yöntem zaten geri döndü, tekrar geri dönemez (ikinci kez yok). Peki arayan kim bilir? Her şey hakkında Görevler! Görev iade edildi. Görev beklendi (yöntem değil, değer değil). Değer Görevde ayarlanacaktır. Görev durumu tamamlanacak şekilde ayarlanacaktır. Arayan sadece Görev izler. Daha sonra için daha fazla okur burada .

Öğrenme uğruna soru gözden geçirme: 1 dak

Soruyu biraz ayarlayalım:

Nasıl ve Ne Zaman Kullanılır? async ve await Tasks?

Çünkü Task öğrenme diğer 2'yi de otomatik olarak kapsar. En azından öğrenme adına. Tabii ki, bu async ve await hakkındaki sorunuza bir cevap.

Çabuk sözdizimi şekerinden kurtulun: 5 dak

  • Dönüşümden önce (orijinal yöntem)

    internal static int Method(int arg0, int arg1) { int result = arg0 + arg1; IO(); // Do some long running IO. return result; }

  • Yukarıdaki yöntemi çağırmak için başka bir Görev-ified yöntemi

    internal static Task<int> MethodTask(int arg0, int arg1) { Task<int> task = new Task<int>(() => Method(arg0, arg1)); task.Start(); // Hot task (started task) should always be returned. return task; }

Bekledik ya da eşzamansız olarak mı bahsettik? Hayır. Yukarıdaki yöntemi çağırdığınızda bir görev alırsınız. Hangi izleyebilirsin. Görevin ne döndürdüğünü zaten biliyorsun .. bir tamsayı.

  • Görev çağırma biraz zordur. MethodTask () öğesini çağıralım

    internal static async Task<int> MethodAsync(int arg0, int arg1) { int result = await HelperMethods.MethodTask(arg0, arg1); return result; }

Tamamlanacak 'görev bekliyoruz'. Dolayısıyla await. Bekleyiş kullandığımızdan, önek (kodlama standardı) olarak async (zorunlu) ve 'Async' içeren MethodAsync kullanmalıyız. Daha sonra için daha fazla okur burada

Bir geliştiricinin kafasını karıştırın: 5 dak

Bir geliştirici Task uygulamamakta hata yaptı ama hala çalışıyor! Soruyu ve sadece kabul edilen cevabı anlamaya çalışın burada verilmiştir . Umarım okudunuz ve tamamen anladınız. Aynı şekilde bizim örneğimizde zaten yerleşik bir MethodAsync() çağırmak, bu yöntemi Task (MethodTask()) ile kendimiz uygulamaktan çok daha kolaydır. Çoğu geliştirici, bir kodu Eşzamansız olana dönüştürürken, kafasını Tasks etrafında çevirmeyi zor buluyor.

İpucu: Zorluğu dışlamak için mevcut bir Async uygulaması (MethodAsync veya ToListAsync gibi) bulmaya çalışın. Bu yüzden sadece Async ile uğraşmamız ve beklememiz gerekiyor (normal koda kolay ve oldukça benzer)

Sorun: Normal kodun gerçek dünyadaki bir uygulamasını hızla Async işlemine dönüştürün: 2 dak

Aşağıda Veri Katmanında gösterilen kod satırı bozulmaya başladı (birçok yerde). Çünkü bazı kodlarımızı .Net framework 4.2'den .Net core'a yükselttik. Tüm uygulama boyunca bunu 1 saat içinde düzeltmek zorunda kaldık!

var myContract = query.Where(c => c.ContractID == _contractID).First();

tereyağından kıl çeker gibi!

  1. EntityFrameWork nuget (QueryableExtensions vardır)
  2. namespace = Microsoft.EntityFrameworkCore

kod böyle değişti

var myContract = await query.Where(c => c.ContractID == _contractID).FirstAsync();
  1. Yöntem imzası değiştirildi

    Contract GetContract(int contractnumber)

    için

    async Task<Contract> GetContractAsync(int contractnumber)

  2. çağıran yöntem de etkilendi: GetContractAsync(123456);, GetContractAsync(123456).Result; olarak adlandırıldı.

  3. Her yerde 30 dakikada değiştirdik!

Ancak mimar, EntityFrameWork kütüphanesini sadece bunun için kullanmamamızı söyledi! ayy! dram! Sonra özel bir Görev uygulaması yaptık. Hangisini biliyorsun. Hala kolay!

Nereden Sonraki? İzleyebileceğimiz harika bir hızlı video var Senkronize Aramaları ASP.Net Çekirdeğinde Senkronize Olarak Dönüştürme , Çünkü bu muhtemelen bunu okuduktan sonra gideceğiniz yöndür.

5
Blue Clouds
public static void Main(string[] args)
{
    string result = DownloadContentAsync().Result;
    Console.ReadKey();
}

// You use the async keyword to mark a method for asynchronous operations.
// The "async" modifier simply starts synchronously the current thread. 
// What it does is enable the method to be split into multiple pieces.
// The boundaries of these pieces are marked with the await keyword.
public static async Task<string> DownloadContentAsync()// By convention, the method name ends with "Async
{
    using (HttpClient client = new HttpClient())
    {
        // When you use the await keyword, the compiler generates the code that checks if the asynchronous operation is finished.
        // If it is already finished, the method continues to run synchronously.
        // If not completed, the state machine will connect a continuation method that must be executed WHEN the Task is completed.


        // Http request example. 
        // (In this example I can set the milliseconds after "sleep=")
        String result = await client.GetStringAsync("http://httpstat.us/200?sleep=1000");

        Console.WriteLine(result);

        // After completing the result response, the state machine will continue to synchronously execute the other processes.


        return result;
    }
}
3

Daha yüksek düzeyde:

1) Async anahtar sözcüğü beklemeyi sağlar ve hepsi bu. Async anahtar sözcüğü, yöntemi ayrı bir iş parçacığında çalıştırmaz. Başlangıç ​​f async yöntemi, zaman alıcı bir görevde bekleyene kadar eşzamanlı olarak çalışır.

2) Görev veya T tipinde Görev döndüren bir yöntem bekleyebilirsiniz. Asenkron void yönteminde bekleyemezsiniz.

3) Ana iş parçacığının karşılaştığı an zaman alan görevde bekler veya asıl iş başladığında, ana iş parçacığı geçerli yöntemin arayana döner. 

4) Ana iş parçacığı hala yürütülmekte olan bir görevi beklerse, beklemez ve geçerli yöntemin arayanına döner. Bu şekilde, uygulama duyarlı kalır.

5) İşleme devam etmeyi bekliyor, şimdi iş parçacığı havuzundan ayrı bir iş parçacığında yürütecek.

6) Bu bekleyen görev tamamlandığında, altındaki tüm kod ayrı bir konu tarafından yürütülür.

Örnek kod aşağıdadır. Çalıştırın ve konu kimliğini kontrol edin

using System;
using System.Threading;
using System.Threading.Tasks;

namespace AsyncAwaitDemo
{
    class Program
    {
        public static async void AsynchronousOperation()
        {
            Console.WriteLine("Inside AsynchronousOperation Before AsyncMethod, Thread Id: " + Thread.CurrentThread.ManagedThreadId);
            //Task<int> _task = AsyncMethod();
            int count = await AsyncMethod();

            Console.WriteLine("Inside AsynchronousOperation After AsyncMethod Before Await, Thread Id: " + Thread.CurrentThread.ManagedThreadId);

            //int count = await _task;

            Console.WriteLine("Inside AsynchronousOperation After AsyncMethod After Await Before DependentMethod, Thread Id: " + Thread.CurrentThread.ManagedThreadId);

            DependentMethod(count);

            Console.WriteLine("Inside AsynchronousOperation After AsyncMethod After Await After DependentMethod, Thread Id: " + Thread.CurrentThread.ManagedThreadId);
        }

        public static async Task<int> AsyncMethod()
        {
            Console.WriteLine("Inside AsyncMethod, Thread Id: " + Thread.CurrentThread.ManagedThreadId);
            int count = 0;

            await Task.Run(() =>
            {
                Console.WriteLine("Executing a long running task which takes 10 seconds to complete, Thread Id: " + Thread.CurrentThread.ManagedThreadId);
                Thread.Sleep(20000);
                count = 10;
            });

            Console.WriteLine("Completed AsyncMethod, Thread Id: " + Thread.CurrentThread.ManagedThreadId);

            return count;
        }       

        public static void DependentMethod(int count)
        {
            Console.WriteLine("Inside DependentMethod, Thread Id: " + Thread.CurrentThread.ManagedThreadId + ". Total count is " + count);
        }

        static void Main(string[] args)
        {
            Console.WriteLine("Started Main method, Thread Id: " + Thread.CurrentThread.ManagedThreadId);

            AsynchronousOperation();

            Console.WriteLine("Completed Main method, Thread Id: " + Thread.CurrentThread.ManagedThreadId);

            Console.ReadKey();
        }

    }
}
3
ABajpai

Anladığım kadarıyla, bu karışıma eklenen üçüncü bir terim olmalıdır: Task.

Async, yönteminizin eşzamansız olmayan bir yöntem olduğunu söylemek için kullandığınız bir niteleyicidir.

Task, async işlevinin dönüşüdür. Zaman uyumsuz olarak yürütülür.

Siz await bir Görev. Kod yürütme bu satıra ulaştığında, kontrol çevrenizdeki orijinal işlevini arayan kişiye geri döner.

Bunun yerine, bir değişkene async işlevinin (yani Task) dönüşünü bir değişkene atarsınız, kod yürütme bu satıra ulaştığında, sadece devam et / o karakterin çevresindeki işlevde while Task zaman uyumsuz olarak çalışır.

2
user21306

Aşağıdaki kodda, HttpClient yöntemi GetByteArrayAsync, bir Görev getContentsTask döndürür. Görev, görev tamamlandığında gerçek bayt dizisini üretmeye söz veriyor. Bekleyen işleç, getContentsTask tamamlanana kadar SumPageSizesAsync'deki yürütmeyi askıya almak için getContentsTask öğesine uygulanır. Bu arada, kontrol SumPageSizesAsync arayana geri verilir. GetContentsTask bittiğinde, bekliyor ifadesi bir bayt dizisini değerlendirir.

private async Task SumPageSizesAsync()
{
    // To use the HttpClient type in desktop apps, you must include a using directive and add a 
    // reference for the System.Net.Http namespace.
    HttpClient client = new HttpClient();
    // . . .
    Task<byte[]> getContentsTask = client.GetByteArrayAsync(url);
    byte[] urlContents = await getContentsTask;

    // Equivalently, now that you see how it works, you can write the same thing in a single line.
    //byte[] urlContents = await client.GetByteArrayAsync(url);
    // . . .
}
1
lazydeveloper

Asenkron/Bekleyen

Aslında Async/Await, asenkron bir görevin geri çağrısını oluşturmak için sadece sözdizimsel şeker olan bir çift anahtar kelimedir.

Bu işlemi örnek olarak alın:

    public static void DoSomeWork()
    {
        var task = Task.Run(() =>
        {
            // [RUNS ON WORKER THREAD]

            // IS NOT bubbling up due to the different threads
            throw new Exception();
            Thread.Sleep(2000);

            return "Hello";
        });

        // This is the callback
        task.ContinueWith((t) => {
            // -> Exception is swallowed silently
            Console.WriteLine("Completed");

            // [RUNS ON WORKER THREAD]
        });
    }

Bu yöntemin birkaç dezavantajı vardır. Hatalar geçilmez ve okunması son derece zordur .Ama Async ve Await bize yardım etmek için içeri girdi:

    public async static void DoSomeWork()
    {
        var result = await Task.Run(() =>
        {
            // [RUNS ON WORKER THREAD]

            // IS bubbling up
            throw new Exception();
            Thread.Sleep(2000);

            return "Hello";
        });

        // every thing below is a callback 
        // (including the calling methods)

        Console.WriteLine("Completed");

    }

Bekleyen aramalar Async yöntemlerinde olmalıdır. Bunun bazı avantajları vardır:

  • Görev sonucunu döndürür
  • otomatik olarak bir geri arama oluşturur
  • hataları denetler ve arama zincirinde konuşmalarını sağlar (yalnızca arama zincirinde beklemeden aramalara kadar)
  • sonucu bekler
  • ana ipliği serbest bırakır
  • ana iş parçacığı üzerinde geri aramayı çalıştırır
  • görev için threadpool'dan bir iş parçacığı kullanıyor
  • kodun okunmasını kolaylaştırır
  • ve çok daha fazlası

NOTU: Async ve Await, bunları yapmak için with asenkron çağrılarda değil kullanılır. Task.Run () gibi bunun için Task Libary kullanmanız gerekir.

İşte bekleyen ve hiçbiri bekleyen çözümler arasında bir karşılaştırma

Bu, hiçbir zaman uyumsuz çözümdür:

    public static long DoTask()
    {
        stopWatch.Reset();
        stopWatch.Start();

        // [RUNS ON MAIN THREAD]
        var task = Task.Run(() => {
            Thread.Sleep(2000);
            // [RUNS ON WORKER THREAD]
        });
        Thread.Sleep(1000);
        // goes directly further
        // WITHOUT waiting until the task is finished

        // [RUNS ON MAIN THREAD]

        stopWatch.Stop();
        // 50 milliseconds
        return stopWatch.ElapsedMilliseconds;
    }

Bu zaman uyumsuz bir yöntemdir:

    public async static Task<long> DoAwaitTask()
    {
        stopWatch.Reset();
        stopWatch.Start();

        // [RUNS ON MAIN THREAD]

        await Task.Run(() => {
            Thread.Sleep(2000);
            // [RUNS ON WORKER THREAD]
        });
        // Waits until task is finished

        // [RUNS ON MAIN THREAD]

        stopWatch.Stop();
        // 2050 milliseconds
        return stopWatch.ElapsedMilliseconds;
    }

Gerçekten beklenmedik anahtar sözcüğü olmadan bir eşzamansız yöntemini çağırabilirsiniz, ancak bu, buradaki herhangi bir İstisna'nın yayın modunda yutulduğu anlamına gelir:

    public static Stopwatch stopWatch { get; } = new Stopwatch();

    static void Main(string[] args)
    {
        Console.WriteLine("DoAwaitTask: " + DoAwaitTask().Result + " ms");
        // 2050 (2000 more because of the await)
        Console.WriteLine("DoTask: " + DoTask() + " ms");
        // 50
        Console.ReadKey();
    }

Eşzamansız ve Bekleyen paralel hesaplama için uygun değildir. Ana ipliğinizi engellememek için kullanılırlar. ASP.NET veya Windows uygulamaları hakkında ise. Bir ağ araması nedeniyle ana iş parçacığınızı engellemek kötü bir şeydir. Bunu yaparsanız, uygulamanız yanıt vermiyor veya çökebilir.

Bazı örnekler almak için ms docs adresini ziyaret edin.

1
Hakim

uzun .__ yapmak için onları arka plan ipliklerine yumurtlamaya eşit kullanıyor. süre mantığı?

Bu makale MDSN: Asenkron ve bekleyen Asenkron Programlama (C #) açıkça açıklar:

Eşzamansız ve bekleyen anahtar kelimeler, ek iş parçacıklarının kullanılmamasına neden olur. yarattı. Zaman uyumsuz yöntemler çoklu okuma gerektirmez, çünkü zaman uyumsuz. yöntem kendi iş parçacığında çalışmaz. Bu yöntem geçerli .__ üzerinde çalışır. senkronizasyon bağlamı ve iş parçacığı üzerinde yalnızca zaman kullanır. yöntem etkin.

1
Dmitry G.

Aşağıdakiler, ne zaman kullanacağınıza ve ne zaman async bekleyeceğimize karar vermek için kullandığım temel kurallar.

  1. Zaman uyumsuz işlevi bir söz verir. Konuşma da doğrudur. Bir söz veren her işlev, bir eşzamansız işlevi çağırmak için kullanılır ve çözümlenmesini veya reddedilmesini bekler.

  2. bekleyen, kodun içinde bulunduğu zaman uyumsuz işlevi içinde yürütülmesini engeller. Eğer işlev2'nin çıktısı işlev1'in çıktısına bağlıysa o zaman beklerim.

  3. İki fonksiyon paralel olarak çalıştırılabiliyorsa iki farklı asenkron fonksiyon oluşturun ve ardından paralel olarak çalıştırın.

  4. Paralel olarak sözler çalıştırmak için bir dizi sözler oluşturun ve ardından Promise.all (promisesArray) kullanın. Her kullanışınızda, engelleme kodu yazdığınızı unutmayın. Zamanla bunu ihmal etme eğilimindeyiz.

  5. İçinde çok sayıda asyncFunction () bekleyen async fonksiyonları oluşturmak yerine, daha küçük async fonksiyonları oluşturmak daha iyidir. Bu şekilde, çok fazla engelleme kodu yazmadığımızı fark edeceğiz. Küçük async işlevlerini kullanmanın bir başka avantajı, paralel olarak çalıştırılabilecek async işlevlerinin ne olduğunu düşünmeye zorlamanızdır.

  6. Kodunuz engelleyici kod içeriyorsa, bir uyumsuzluk yapmak daha iyidir. Bunu yaparak, başka birinin işlevinizi zaman uyumsuz olarak kullanabildiğinden emin olursunuz.

  7. Blokaj kodunun dışında zaman uyumsuz işlevler yaparak, işlevini çağıran kullanıcının istediği zaman uyumsuzluk düzeyine karar vermesini sağlarsınız.

Umarım bu, ne zaman ve ne zaman kullanacağınıza, ne zaman ve ne zaman kullanacağınıza karar vermenize yardımcı olur.

0
Sunny Sultan

Aşağıda iletişim kutusunu açarak Excel dosyasını okuyan ve ardından eşzamansız kullanan ve eşzamanlı olarak çalıştırmak için bekleyin, Excel'den tek tek satır okuyan ve kılavuza bağlanan kod 

namespace EmailBillingRates
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            lblProcessing.Text = "";
        }

        private async void btnReadExcel_Click(object sender, EventArgs e)
        {
            string filename = OpenFileDialog();

            Microsoft.Office.Interop.Excel.Application xlApp = new Microsoft.Office.Interop.Excel.Application();
            Microsoft.Office.Interop.Excel.Workbook xlWorkbook = xlApp.Workbooks.Open(filename);
            Microsoft.Office.Interop.Excel._Worksheet xlWorksheet = xlWorkbook.Sheets[1];
            Microsoft.Office.Interop.Excel.Range xlRange = xlWorksheet.UsedRange;
            try
            {
                Task<int> longRunningTask = BindGrid(xlRange);
                int result = await longRunningTask;

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message.ToString());
            }
            finally
            {
                //cleanup  
               // GC.Collect();
                //GC.WaitForPendingFinalizers();

                //rule of thumb for releasing com objects:  
                //  never use two dots, all COM objects must be referenced and released individually  
                //  ex: [somthing].[something].[something] is bad  

                //release com objects to fully kill Excel process from running in the background  
                Marshal.ReleaseComObject(xlRange);
                Marshal.ReleaseComObject(xlWorksheet);

                //close and release  
                xlWorkbook.Close();
                Marshal.ReleaseComObject(xlWorkbook);

                //quit and release  
                xlApp.Quit();
                Marshal.ReleaseComObject(xlApp);
            }

        }

        private void btnSendEmail_Click(object sender, EventArgs e)
        {

        }

        private string OpenFileDialog()
        {
            string filename = "";
            OpenFileDialog fdlg = new OpenFileDialog();
            fdlg.Title = "Excel File Dialog";
            fdlg.InitialDirectory = @"c:\";
            fdlg.Filter = "All files (*.*)|*.*|All files (*.*)|*.*";
            fdlg.FilterIndex = 2;
            fdlg.RestoreDirectory = true;
            if (fdlg.ShowDialog() == DialogResult.OK)
            {
                filename = fdlg.FileName;
            }
            return filename;
        }

        private async Task<int> BindGrid(Microsoft.Office.Interop.Excel.Range xlRange)
        {
            lblProcessing.Text = "Processing File.. Please wait";
            int rowCount = xlRange.Rows.Count;
            int colCount = xlRange.Columns.Count;

            // dt.Column = colCount;  
            dataGridView1.ColumnCount = colCount;
            dataGridView1.RowCount = rowCount;

            for (int i = 1; i <= rowCount; i++)
            {
                for (int j = 1; j <= colCount; j++)
                {
                    //write the value to the Grid  
                    if (xlRange.Cells[i, j] != null && xlRange.Cells[i, j].Value2 != null)
                    {
                         await Task.Delay(1);
                         dataGridView1.Rows[i - 1].Cells[j - 1].Value =  xlRange.Cells[i, j].Value2.ToString();
                    }

                }
            }
            lblProcessing.Text = "";
            return 0;
        }
    }

    internal class async
    {
    }
}
0
Zaheer Abbas

Zaman uyumsuz ve basit bir açıklama bekliyor

Basit Analoji

Bir kişi sabah treni için bekle olabilir. Yaptıkları tek şey bu, şu anda gerçekleştirdikleri birincil görev. (senkron programlama) (normalde ne yaparsınız?))

Bir başka kişi, sigara içip kahvelerini içerken sabah trenine bekliyor. (Asenkron programlama)

Zaman uyumsuz programlama nedir?

Eşzamansız programlama, bir programcının kodunun bir bölümünü yürütmenin ana iş parçacığından ayrı bir iş parçacığında çalıştırmayı seçtiğinde ve ardından iş parçacığının tamamlandığını bildirir.

Async anahtar sözcüğü gerçekte ne yapar?

Async anahtar sözcüğünü aşağıdaki gibi bir yöntem adına ön ekleme 

async void DoSomething(){ . . .

programcının zaman uyumsuz görevleri çağırırken await anahtar sözcüğünü kullanmasına izin verir. Hepsi bu kadar.

Bu neden önemli?

Birçok yazılım sisteminde ana iş parçacığı, Kullanıcı Arabirimi ile ilgili işlemler için ayrılmıştır. Bilgisayarımda tamamlamak için 5 saniye süren çok karmaşık bir özyinelemeli algoritma çalıştırıyorum, ancak bunu Ana Konu üzerinde çalıştırıyorum (UI thread) Kullanıcı uygulamamdaki herhangi bir şeyi tıklamaya çalıştığında, donmuş gibi görünüyor ana iş parçamı sıraya girmiş ve şu anda çok fazla işlem gerçekleştiriyor. Sonuç olarak, ana iş parçacığı, düğmeyi tıklatarak yöntemi çalıştırmak için fare tıklatmasını işleyemez.

Async ve Await'i ne zaman kullanıyorsunuz?

Asenkron anahtar kelimeleri, kullanıcı arayüzünü içermeyen herhangi bir şey yaparken ideal olarak kullanın. 

Öyleyse, kullanıcının cep telefonuna çizim yapmasına izin veren bir program yazdığınızı varsayalım, ancak her 5 saniyede bir, internetteki havayı kontrol ediyor olacak.

Uygulamanın kullanıcısı, güzel resimler çekmek için mobil dokunmatik ekranla etkileşime girmeye devam etmesi gerektiğinden, havayı almak için her 5 saniyede bir yoklama çağrıları şebekesini beklemeliyiz.

Async ve Await'i nasıl kullanırsınız

Yukarıdaki örnekten sonra, nasıl yazılacağına dair bazı sahte kodlar:

     //ASYNCHRONOUS
    //this is called every 5 seconds
    async void CheckWeather()
    {
        var weather = await GetWeather();
        //do something with the weather now you have it
    }

    async Task<WeatherResult> GetWeather()
    {

        var weatherJson = await CallToNetworkAddressToGetWeather();
        return deserializeJson<weatherJson>(weatherJson);
    }

    //SYNCHRONOUS
    //This method is called whenever the screen is pressed
    void ScreenPressed()
    {
        DrawSketchOnScreen();
    }
0
James Mallon

Buradaki cevaplar, bekleyen/zaman uyumsuz hakkında genel bir rehber olarak faydalıdır. Ayrıca, nasıl beklediğiniz/zaman uyumsuzluğunun kablolu olduğu hakkında da bazı detaylar içerir. Bu tasarım modelini kullanmadan önce bilmeniz gereken bazı pratik deneyimleri sizinle paylaşmak istiyorum.

"Beklemede" terimi gerçek anlamlıdır, bu nedenle hangi konuya başlasanız, devam etmeden önce yöntemin sonucunu bekleyecektir. Foreground iş parçasında, bu bir felaket 'dir. Ön plan ipliği, görünümler, modeller, başlangıçtaki animasyonlar ve bu öğelerle baştan aşağı bağladığınız her şey dahil uygulamanızı oluşturma yükünü taşır. Öyleyse ön plan iş parçacığını beklerken, uygulamanın durdur. Kullanıcı hiçbir şey olmadığında bekler ve bekler. Bu, olumsuz bir kullanıcı deneyimi sağlar.

Çeşitli araçlar kullanarak bir arka plan iş parçacığını kesinlikle bekleyebilirsiniz:

Device.BeginInvokeOnMainThread(async () => { await AnyAwaitableMethod(); });

// Notice that we do not await the following call, 
// as that would tie it to the foreground thread.
try
{
Task.Run(async () => { await AnyAwaitableMethod(); });
}
catch
{}

Bu açıklamalar için tam kod https://github.com/marcusts/xamarin-forms-annoyances şeklindedir. AwaitAsyncAntipattern.sln adlı çözüme bakın.

GitHub sitesi ayrıca bu konuyla ilgili daha ayrıntılı bir tartışmaya bağlantılar sunar.

0
Stephen Marcus