Soru Zaman uyumsuz yöntemini senkronize olarak çağırma


Benim bir async yöntem:

public async Task<string> GenerateCodeAsync()
{
    string code = await GenerateCodeService.GenerateCodeAsync();
    return code;
}

Bu yöntemi eşzamanlı bir yöntemle çağırmalıyım.

Bunu çoğaltmak zorunda kalmadan bunu nasıl yapabilirim? GenerateCodeAsync Bunun senkronize olarak çalışması için yöntem mi?

Güncelleştirme

Ancak makul bir çözüm bulunamadı.

Ancak, onu görüyorum HttpClient zaten bunu uygular Desen

using (HttpClient client = new HttpClient())
{
    // async
    HttpResponseMessage responseAsync = await client.GetAsync(url);

    // sync
    HttpResponseMessage responseSync = client.GetAsync(url).Result;
}

171
2018-03-25 07:34


Menşei


olası kopyası Zaman uyumsuz bir Görev <T> yöntemini eşzamanlı olarak nasıl çalıştırırım? - Heinzi
Asp.net'in bu kadar çok kod satırından çok daha kolay işlediğini düşünerek daha basit bir çözüm umuyordum. - Catalin
Neden sadece uyumsuz kod içermiyorsunuz? İdeal olarak, daha az değil, daha fazla uyumsuzluk kodu istersiniz. - Paulo Morgado
[Neden async kodunu benimsemiyoruz?] Ha, projenin büyük bölümleri dönüştürüldükçe bu çözümlere ihtiyaç duydukları için asenkron kodları bir araya getirdiği kesin olabilir! Roma'yı bir günde yeniden inşa edemezsin. - Nicholas Petersen
Peki, bir sonraki adım. İş parçacığı öldürmem gerekiyor, eşzamanlı yöntemimi çalıştırıyorum, bu yüzden GenerateCodeAsync de öldürülmeli. - dimzon


Cevaplar:


Erişebilirsiniz Result Sonucun alınmasına kadar iş parçacığının engellenmesine neden olan görevin özelliği:

string code = GenerateCodeAsync().Result;

Not: Bazı durumlarda, bu bir çıkmazın ortaya çıkmasına neden olabilir: Result Ana threadi bloke eder, böylece async kodunun kalanını yürütür. Bunun olmadığından emin olmak için aşağıdaki seçeneklere sahipsiniz:


230
2018-03-25 08:41



Eğer çağırıyorsa result bir kilitlenme riskini, ne zaman olduğu sonucu almak güvenli mi? Her zaman uyumsuz çağrı gerektirir Task.Run veya ConfigureAwait(false)? - Robert Harvey♦
ASP.NET'te "ana iş parçacığı" yoktur (bir GUI uygulamasından farklı olarak), ancak kilitlenme hala nedeniyle mümkündür Nasıl  AspNetSynchronizationContext.Post async sürekliliğini uyarlar: Task newTask = _lastScheduledTask.ContinueWith(_ => SafeWrapCallback(action)); _lastScheduledTask = newTask; - Noseratio
@RobertHarvey: Engellediğiniz async yönteminin uygulanması üzerinde herhangi bir kontrole sahip değilseniz, o zaman evet, Task.Run güvende kalmak için. Ya da gibi bir şey kullan WithNoContext yedekli iplik anahtarlamayı azaltmak için. - Noseratio
NOT: Arama .Result Arayan iş parçacığı havuzundaysa, yine de kilitlenebilir. İş parçacığı havuzu 32 ve 32 görevlerin çalıştırıldığı bir senaryo alın. Wait()/Result bekleyen iş parçacıklarından birinde çalışmak isteyen henüz planlanmamış bir 33 görev bekliyorum. - Warty


Bekçiyi almalısın (GetAwaiter()) ve eşzamansız görevin tamamlanmasını beklemekGetResult()).

string code = GenerateCodeAsync().GetAwaiter().GetResult();

41
2017-11-28 23:21



Teşekkürler, kodunuz benim problemimi çözdü. - Murat ÖNER
Bu çözümü kullanarak çıkmazlara girdik. Uyarılırsınız. - Oliver
MSDN Task.GetAwaiter: Bu yöntem, uygulama kodunda kullanmak yerine derleyici kullanımı için tasarlanmıştır. - foka


Bunu delegeler, lambda ifadesi kullanarak yapabilmelisiniz.

private void button2_Click(object sender, EventArgs e)
    {

        label1.Text = "waiting....";

        Task<string> sCode = Task.Run(async () =>
        {
            string msg =await GenerateCodeAsync();
            return msg;
        });

        label1.Text += sCode.Result;

    }

    private Task<string> GenerateCodeAsync()
    {
        return Task.Run<string>(() => GenerateCode());
    }

    private string GenerateCode()
    {
        Thread.Sleep(2000);
        return "I m back" ;
    }

27
2018-05-07 08:07



Bu snippet derlenmeyecek. Task.Run'dan gelen görev türü Görev'dir. Bunu gör MSDN blogu tam açıklama için. - Appetere
İşaretlediğiniz için teşekkürler, evet Görev tipi döndürür. "String sCode" öğesinin Görev <string> veya var sCode yerine değiştirilmesi sorunu çözmelidir. Kolaylık için tam bir derleme kodu eklemek. - Faiyaz


Bu yöntemi eşzamanlı bir yöntemle çağırmalıyım.

İle mümkündür GenerateCodeAsync().Result veya GenerateCodeAsync().Wait()Diğer cevabın da ileri sürdüğü gibi. Bu, mevcut iş parçacığını engeller. GenerateCodeAsync tamamlandı.

Ancak, sorunuzla etiketlendi ve siz de yorumu bıraktınız:

Asp.net'in işlediğini düşünerek daha basit bir çözüm umuyordum.   Bu kadar çok kod satırı yazmaktan çok daha kolay

Benim amacım sen engellememeli ASP.NET'te eşzamansız bir yöntem. Bu, web uygulamanızın ölçeklenebilirliğini azaltacak ve bir kilitlenme yaratabilecek await içeride devam GenerateCodeAsync gönderildiği AspNetSynchronizationContext). kullanma Task.Run(...).Result Bir havuz iş parçacığına bir şey boşaltmak ve daha sonra engellemek, ölçeklendirilebilirliği daha da artırır, çünkü belirli bir HTTP isteğini işlemek için +1 daha fazla iş parçacığı oluşturur.

ASP.NET, eşzamansız denetimler (ASP.NET MVC ve Web API'sı) aracılığıyla veya doğrudan yoluyla eşzamansız yöntemler için yerleşik bir desteğe sahiptir. AsyncManager ve PageAsyncTask klasik ASP.NET'te. Kullanmalısın. Daha fazla bilgi için, kontrol edin bu cevap.


18
2018-03-25 10:56



Üstüne yazıyorum SaveChanges() yöntem DbContextve burada async yöntemlerini arıyorum, maalesef asenkron denetleyici bu durumda bana yardımcı olmayacak - Catalin
@RaraituL, genel olarak, uyumsuz ve senkronizasyon kodunu karıştırmaz, euther modelini seçersiniz. İkisini de uygulayabilirsiniz SaveChangesAsync ve SaveChangesSadece, aynı ASP.NET projesinde de çağrılmadıklarından emin olun. - Noseratio
Hepsi değil .NET MVC filtreler örneğin senkronize olmayan kodu destekler IAuthorizationFilterbu yüzden kullanamam async bütün yol - Catalin
@Noseratio bu gerçekçi olmayan bir hedeftir. Eşzamanlı olmayan ve senkronize kodlu çok sayıda kütüphane ve sadece bir modelin kullanılmasının mümkün olmadığı durumlar vardır. MVC ActionFilters, örneğin senkronize olmayan kodu desteklemiyor. - Justin Skiles
@Noserato, asenkronize yöntemi senkronize olarak aramakla ilgili soru. Bazen, uyguladığınız API'yi değiştiremezsiniz. Bazı 3-boyutlu parti çerçevesinin "A" (eşzamansız bir şekilde yeniden yazamazsınız) bazı senkronize arayüzleri uyguladığınızı varsayalım, fakat uygulamanızda kullanmaya çalıştığınız 3. parti kütüphane "B" nin sadece asenkronize olduğunu göreceksiniz. Ayrıca ortaya çıkan ürün de kütüphanedir ve ASP.NET vb. Dahil her yerde kullanılabilir. - dimzon


Microsoft Identity, eşzamansız olarak eşzamansız yöntemleri çağıran uzantı yöntemlerine sahiptir. Örneğin GenerateUserIdentityAsync () yöntemi ve eşit CreateIdentity () vardır.

UserManagerExtensions.CreateIdentity () 'ye bakarsanız şuna benziyor:

 public static ClaimsIdentity CreateIdentity<TUser, TKey>(this UserManager<TUser, TKey> manager, TUser user,
        string authenticationType)
        where TKey : IEquatable<TKey>
        where TUser : class, IUser<TKey>
    {
        if (manager == null)
        {
            throw new ArgumentNullException("manager");
        }
        return AsyncHelper.RunSync(() => manager.CreateIdentityAsync(user, authenticationType));
    }

Şimdi AsyncHelper.RunSync'in ne yaptığını görelim

  public static TResult RunSync<TResult>(Func<Task<TResult>> func)
    {
        var cultureUi = CultureInfo.CurrentUICulture;
        var culture = CultureInfo.CurrentCulture;
        return _myTaskFactory.StartNew(() =>
        {
            Thread.CurrentThread.CurrentCulture = culture;
            Thread.CurrentThread.CurrentUICulture = cultureUi;
            return func();
        }).Unwrap().GetAwaiter().GetResult();
    }

Yani, bu async yöntemi için sarmalayıcı. Ve lütfen sonuçları Sonucu'dan okuma - kodunuzu ASP'de potansiyel olarak engeller.

Başka bir yol var - ki benim için şüpheli, ama sen de bunu düşünebilirsin

  Result r = null;

            YourAsyncMethod()
                .ContinueWith(t =>
                {
                    r = t.Result;
                })
                .Wait();

10
2017-07-18 22:03



Önerdiğiniz ikinci yolla ilgili sorun nedir? - David Clarke