C # Task.FromResult <TResult> için ne kullanılır?


189

C # ve TPL'de ( Görev Paralel Kütüphanesi ), Tasksınıf T tipi bir değer üreten devam eden bir çalışmayı temsil eder.

Task.FromResult yöntemine ne gerek olduğunu bilmek ister misiniz ?

Yani: Halihazırda üretilen değere sahip olduğunuz bir senaryoda, onu bir Göreve geri sarmak için ne gerekir?

Akla gelen tek şey, bir Görev örneğini kabul eden diğer yöntemler için bazı bağdaştırıcı olarak kullanılmasıdır.


4
bu size yardımcı oluyor mu? msdn.microsoft.com/en-us/library/hh228607.aspx
Izikon

30
Bir dereceye kadar buna katılıyorum, ancak bunun gibi yoğun, yararlı, konsolide, tartışma odaklı sayfaların oluşturulması çok büyük bir fayda. Neredeyse her zaman iyi, yoğun bir stackoverflow sayfasından googling ve birden fazla yerde araştırma yapmaktan daha fazla şey öğreniyorum, bu durumda, bunu gönderdiğine gerçekten sevindim.
Alex Edelstein

41
Sanırım Google beni SO'ya getiriyor ve SO benden Google'a gitmemi istiyor. Dairesel bir referanstır :)
Gmail kullanıcısı

Yanıtlar:


258

Bulduğum iki yaygın kullanım durumu var:

  1. Eşzamansız arayanlara izin veren bir arayüz uygularken, ancak uygulamanız eşzamanlıdır.
  2. Test etmek için eşzamansız kodu alay ederken / alay ederken.

6
# 1 için iyi bir durum bir web hizmetidir. Geri dönen bir eşzamanlı hizmet yönteminiz Task.FromResultve ağ G / Ç için eşzamansız olarak bekleyen bir istemciniz olabilir. Bu şekilde aynı arabirimi kullanarak istemci / sunucu arasında paylaşabilirsiniz ChannelFactory.
Nelson Rothermel

2
Örneğin, ChallengeAsync yöntemi. MS düşüncesindeki tasarımcılar WTF idi? Bu yöntemin bir Görev döndürmesi için kesinlikle hiçbir neden yoktur. Ve MS'nin tüm örnek kodunda FromResult (0) vardır. Umarım derleyici bunu optimize edecek kadar akıllıdır ve aslında yeni bir iş parçacığı oluşturmaz ve hemen öldürmez!
John Henckel

14
@JohnHenckel: OWIN sıfırdan asenkron dostu olacak şekilde tasarlanmıştır. O sırf Arayüzler ve baz sınıfları genellikle imzalar zaman uyumsuz kullanmak verir (değil kuvvetleri ) uygulaması zaman uyumsuz olması. Buna benzer Yani IEnumerable<T>doğan IDisposable- bu izin veren enumerable tek kullanımlık kaynaklara değil, var güçlerini o kadar. Ne FromResult, asyncne de awaitkonuları doğurur.
Stephen Cleary

4
@StephenCleary hmhm, bunu açıkladığınız için teşekkürler. Beklemenin doğacağını varsaymıştım, ama denedim ve görmüyorum. Sadece Görev.Run yapar. Bu nedenle, x = Görev Beklenir. Sonuç (0); x = 0; bu kafa karıştırıcı, ama bilmek güzel!
John Henckel

4
@OlegI: G / Ç işlemleri için en iyi çözüm, zaman uyumsuz olarak uygulamaktır, ancak bazen bu seçeneğiniz olmaz. Ayrıca, bazen olabilir (değer önbelleğe değilse uyumsuz bir uygulamaya geri düşen, örneğin önbelleğe alınmış sonucu) eşzamanlı olarak uygulanması. Daha genel olarak, bir Taskgeri dönüş yöntemi, " asenkron olabilir " anlamına gelir . Bu nedenle, bazen yöntemlere, bazı uygulamaların senkronize olacağını (örneğin, senkronize olmayan NetworkStream, ancak MemoryStreamsenkronize olması gerektiğini) iyi bilen asenkron bir imza verilir .
Stephen Cleary

50

Örnek olarak önbellek kullanan bir yöntem verilebilir. Sonuç zaten hesaplanmışsa, tamamlanmış bir görevi değeriyle (kullanarak Task.FromResult) döndürebilirsiniz . Değilse, devam edip devam eden işi temsil eden bir görev döndürürsünüz.

Önbellek Örneği: Önceden hesaplanmış değerler için Task.FromResult kullanılan önbellek örneği


Ve geri gönderilenler gibi tamamlanmış görevler Task.FromResultönbelleğe alınabilir.
Paulo Morgado

1
@Paulo: Görev nesnesinin tamamını bellekte tutmak, yalnızca sonucu önbelleğe almaktan çok daha israflı görünüyor.
Ben Voigt

2
"Değer görevleri" nin zaten önbelleğe alınmasını bekleyin. Tam olarak hangi olanları hatırlamıyorum, ama sanırım Task.FromResult(0), Task.FromResult(1), Task.FromResult(false)ve Task.FromResult(true)önbelleğe alınır. Bir ağ erişimi için bir görevi önbelleğe almanız gerekmez, ancak sonuçtan bir görev mükemmel olur. Her değer döndürmeniz gerektiğinde bir tane oluşturmak ister misiniz?
Paulo Morgado

4
... ve kendi sorumu cevaplamak için, Görevler önbelleğinin yararı, bazı görevlerin tamamlanabilmesi, diğerlerinin ise henüz bitmemiş olabilmeleridir. Arayanlar umursamaz: asenkron bir çağrı yaparlar ve zaten tamamlandıysa, beklediklerinde hemen bir cevap alırlar, değilse, daha sonra alırlar. Bu önbelleğe alınmış görevler olmadan, (a) iki farklı mekanizma gerektirir, bir senkronizasyon ve bir eşzamansız - arayan için hantal, veya (b) bir arayan zaten mevcut olan her cevap istediğinde dinamik olarak bir Görev oluşturmanız gerekir sadece bir TResult önbelleğe almıştı).
ToolmakerSteve

1
Şimdi anladım. Cevabın ifadesi biraz kafa karıştırıcıydı. Görevin kendisinde yerleşik bir "önbellek" mekanizması yoktur. Ancak ... diyelim ki ... dosyaları indirmek, Görev <Dosya> GetFileAync () için bir önbellek mekanizması yazdıysanız, Task.FromResult (cachedFile) ve beklemede kullanarak önbellekte olan bir dosyayı anında döndürebilirsiniz. zaman, iplik anahtarına sahip olmadan zaman kazanır.
Brain2000

31

Zaman uyumsuz anahtar kelimeyi kullanmadan beklenen bir yöntem oluşturmak istediğinizde kullanın. Bu örneği buldum:

public class TextResult : IHttpActionResult
{
    string _value;
    HttpRequestMessage _request;

    public TextResult(string value, HttpRequestMessage request)
    {
        _value = value;
        _request = request;
    }
    public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
    {
        var response = new HttpResponseMessage()
        {
            Content = new StringContent(_value),
            RequestMessage = _request
        };
        return Task.FromResult(response);
    }
}

Burada, bir Web Api Eyleminde kullanılacak IHttpActionResult arabirimini kendi uygulamanızı oluşturuyorsunuz. ExecuteAsync yönteminin eşzamansız olması beklenir, ancak eşzamansız ve beklenebilir hale getirmek için eşzamansız anahtar kelimeyi kullanmanız gerekmez. Zaten sonuca sahip olduğunuzdan ve hiçbir şey beklemenize gerek olmadığından, Görev'i kullanmak daha iyidir.



4

Eşzamansız bir işlem yapmak istediğinizde, ancak bazen sonuç eşzamanlı olarak elinizde olduğunda Task.FromResult öğesini kullanın. Burada iyi bir örnek bulabilirsiniz http://msdn.microsoft.com/en-us/library/hh228607.aspx .


iyi örneğinizde, sonuç eşzamanlı olarak ellerde değildir, işlemin tümü eşzamansızdır, Task.FromResultdaha önce önbelleğe alınmış bir eşzamansız sonuç elde etmek için kullanılır.
Rodrigo Reis

1

Kodunuzda başka bir bağımsız çalışma yaparken, tamamlanması uzun zaman alan senkronize yöntemler için Task.FromResult'u kullanabileceğinizi iddia ediyorum. Ben olsa async çağırmak için bu yöntemleri yapmak yerine. Ama denilen kod üzerinde herhangi bir kontrole sahip olmadığınızı ve örtük paralel işlemeyi istediğinizi düşünün.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.