การใช้งานสำหรับ Task.FromResult คืออะไร <TResult> ใน C #


189

ใน C # และ TPL ( Task Parallel Library ) Taskคลาสจะแสดงงานต่อเนื่องที่สร้างมูลค่าประเภท T

ฉันต้องการที่จะรู้ว่าสิ่งที่จำเป็นสำหรับวิธีการTask.FromResult ?

นั่นคือ: ในสถานการณ์ที่คุณมีมูลค่าที่ผลิตอยู่แล้วสิ่งที่จำเป็นต้องห่อกลับเข้าไปในงานคืออะไร?

สิ่งเดียวที่อยู่ในใจคือมันถูกใช้เป็นอะแดปเตอร์สำหรับวิธีการอื่นที่ยอมรับอินสแตนซ์ของงาน


4
มันช่วยคุณได้ไหม msdn.microsoft.com/en-us/library/hh228607.aspx
Izikon

30
ในระดับหนึ่งฉันเห็นด้วยกับเรื่องนั้น แต่การสร้างหน้าเว็บที่เน้นการรวมกลุ่มที่มีประโยชน์หนาแน่นรวมอยู่ด้วยกันเป็นประโยชน์อย่างมาก ฉันมักจะเรียนรู้เพิ่มเติมจากหน้า stackoverflow ที่ดีและหนาแน่นกว่า googling และทำการค้นคว้าในหลาย ๆ แห่งดังนั้นในกรณีนี้ฉันดีใจจริงๆที่เขาโพสต์สิ่งนี้
Alex Edelstein

41
ฉันคิดว่า Google นำฉันมาที่ SO แล้วขอให้ฉันไปที่ Google มันเป็นการอ้างอิงแบบวงกลม :)
ผู้ใช้ gmail

คำตอบ:


258

มีสองกรณีการใช้งานทั่วไปที่ฉันได้พบ:

  1. เมื่อคุณใช้งานอินเทอร์เฟซที่อนุญาตให้ผู้โทรแบบอะซิงโครนัส
  2. เมื่อคุณทำการขัดถู / การเยาะเย้ยรหัสอะซิงโครนัสสำหรับการทดสอบ

6
กรณีที่ดีสำหรับ # 1 คือบริการบนเว็บ คุณอาจมีวิธีการบริการTask.FromResultแบบซิงโครนัสที่ส่งคืนและไคลเอ็นต์ที่รอแบบอะซิงโครนัสสำหรับเครือข่าย I / O วิธีนี้คุณสามารถแบ่งปันอินเตอร์เฟซเดียวกันระหว่างลูกค้า / ChannelFactoryเซิร์ฟเวอร์โดยใช้
Nelson Rothermel

2
ตัวอย่างเช่นเมธอด ChallengeAsync WTF เป็นนักออกแบบที่คิด MS หรือไม่? ไม่มีเหตุผลใดที่วิธีนี้จะส่งคืนภารกิจ และโค้ดตัวอย่างทั้งหมดจาก MS ก็มี FromResult (0) หวังว่าคอมไพเลอร์ฉลาดพอที่จะทำให้สิ่งนี้ดีที่สุดและไม่ได้วางไข่เธรดใหม่แล้วฆ่ามันทันที!
John Henckel

14
@JohnHenckel: OWIN ได้รับการออกแบบมาจากพื้นดินให้เป็นมิตรกับแบบอะซิงก์ อินเทอร์เฟซและคลาสพื้นฐานมักจะใช้ลายเซ็น async เพราะมันช่วยให้ (ไม่บังคับ ) การใช้งานที่จะ async ดังนั้นมันจึงคล้ายกับที่IEnumerable<T>ได้มาจากIDisposable- มันช่วยให้คนนับจำนวนมีทรัพยากรที่ใช้แล้วทิ้งไม่ใช่บังคับให้ ไม่FromResult, asyncหรือawaitจะวางไข่หัวข้อ
Stephen Cleary

4
@StephenCleary hmhm ขอบคุณที่อธิบายว่า ฉันสันนิษฐานว่าการรอคอยจะวางไข่ แต่ฉันลองแล้วเห็นว่าไม่ Task.Run เท่านั้นที่ทำ ดังนั้น x = รอ Task.FromResult (0); เทียบเท่ากับการพูด x = 0; มันช่างสับสน แต่ก็ดีที่รู้!
John Henckel

4
@OlegI: สำหรับการดำเนินงาน I / O ทางออกที่ดีที่สุดคือการใช้แบบอะซิงโครนัส แต่บางครั้งคุณไม่มีตัวเลือกนั้น นอกจากนี้บางครั้งคุณสามารถใช้มันแบบซิงโครนัส (เช่นผลลัพธ์ที่แคชกลับไปสู่การใช้แบบอะซิงโครนัสหากค่าไม่ได้ถูกแคช) โดยทั่วไปแล้วTaskวิธีการเรียกคืนหมายถึง " อาจไม่ตรงกัน" ดังนั้นบางครั้งวิธีการจะได้รับลายเซ็นแบบอะซิงโครนัสรู้ดีว่าการใช้งานบางอย่างจะซิงโครนัส (เช่นNetworkStreamควรเป็นแบบอะซิงโครนัสแต่MemoryStreamควรซิงค์)
Stephen Cleary

50

ตัวอย่างหนึ่งอาจเป็นวิธีที่ใช้ประโยชน์จากแคช หากผลการคำนวณแล้วคุณสามารถกลับงานที่เสร็จสมบูรณ์ด้วยค่า (ใช้Task.FromResult) หากไม่เป็นเช่นนั้นคุณจะดำเนินการต่อและส่งคืนงานที่แสดงถึงงานที่ทำอยู่

ตัวอย่างแคช: ตัวอย่างแคชโดยใช้ Task.FromResult สำหรับค่าที่คำนวณล่วงหน้า


และงานที่เสร็จแล้วเช่นงานที่ส่งคืนจากTask.FromResultสามารถถูกแคชได้
Paulo Morgado

1
@Paulo: การเก็บวัตถุภารกิจทั้งหมดในหน่วยความจำดูเหมือนจะสิ้นเปลืองกว่าการแคชเพียงผลลัพธ์
Ben Voigt

2
คาดว่า "งานค่า" จะถูกแคชไว้แล้ว ผมจำไม่ได้ว่าคนที่ แต่ฉันคิดว่าTask.FromResult(0), Task.FromResult(1), Task.FromResult(false)และTask.FromResult(true)จะถูกเก็บไว้ คุณไม่ควรแคชงานสำหรับการเข้าถึงเครือข่าย แต่อย่างใดอย่างหนึ่งจากผลลัพธ์ได้อย่างสมบูรณ์แบบ คุณต้องการสร้างหนึ่งครั้งทุกครั้งที่คุณต้องการคืนค่าหรือไม่
เปาโล Morgado

4
... และเพื่อตอบคำถามของฉันเองประโยชน์ของแคชของTasksก็คือบางคนสามารถทำงานให้เสร็จได้และบางอย่างก็เป็นงานที่ยังไม่เสร็จ ผู้โทรไม่จำเป็นต้องสนใจพวกเขาทำการโทรแบบอะซิงโครนัสและถ้าเสร็จแล้วพวกเขาจะได้รับคำตอบทันทีเมื่อรอถ้าไม่พวกเขาจะได้รับในภายหลัง หากไม่มีภารกิจที่แคชเหล่านี้จะ (a) ต้องการกลไกที่แตกต่างกันสองแบบหนึ่งการซิงค์และ async หนึ่งอัน - ยุ่งยากสำหรับผู้โทรหรือ (b) ต้องสร้างงานแบบไดนามิกทุกครั้งที่ผู้โทรถามหาคำตอบที่มีอยู่แล้ว (ถ้า เราได้เก็บเฉพาะ TResult เท่านั้น)
ToolmakerSteve

1
ฉันเข้าใจแล้ว. ถ้อยคำของคำตอบนั้นสับสนเล็กน้อย ตัวภารกิจเองไม่มีกลไก "แคช" ในตัว แต่ถ้าคุณเขียนกลไกการแคชสำหรับ ... พูดว่า .... การดาวน์โหลดไฟล์งาน <File> GetFileAync () คุณสามารถส่งคืนไฟล์ที่อยู่ในแคชได้ทันทีโดยใช้ Task.FromResult (cachedFile) และการรอคอย จะเรียกใช้แบบซิงโครนัสประหยัดเวลาโดยไม่มีสวิตช์เธรด
Brain2000

31

ใช้มันเมื่อคุณต้องการสร้างวิธีที่ไม่สามารถรอได้โดยไม่ต้องใช้คำหลัก async ฉันพบตัวอย่างนี้:

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);
    }
}

ที่นี่คุณกำลังสร้างการใช้งานอินเทอร์เฟซ IHttpActionResult ของคุณเองเพื่อใช้ใน Web Api Action กระบวนการ ExecuteAsync คาดว่าจะไม่ตรงกัน แต่คุณไม่จำเป็นต้องใช้คำหลัก async เพื่อทำให้ตรงกันและรอคอย เนื่องจากคุณมีผลลัพธ์อยู่แล้วและไม่จำเป็นต้องรอสิ่งใดเลยควรใช้ Task.FromResult



4

ใช้ Task.FromResult เมื่อคุณต้องการให้มีการดำเนินการแบบอะซิงโครนัส แต่บางครั้งผลลัพธ์จะอยู่ในมือแบบซิงโครนัส คุณสามารถหาตัวอย่างที่ดีได้ที่นี่ http://msdn.microsoft.com/en-us/library/hh228607.aspx


ในตัวอย่างที่ดีของคุณผลลัพธ์ไม่ได้อยู่ในมือพร้อมกันการดำเนินการทั้งหมดเป็นแบบอะซิงโครนัสซึ่งTask.FromResultใช้ในการรับผลลัพธ์ async ที่แคชไว้ก่อนหน้านี้
Rodrigo Reis

1

ฉันจะยืนยันว่าคุณสามารถใช้ Task.FromResult สำหรับวิธีการที่ใช้เวลานานในการดำเนินการในขณะที่คุณสามารถทำงานอิสระอื่น ๆ ในรหัสของคุณ รหัสค่อนข้างทำให้วิธีการเหล่านั้นเรียก async ว่า แต่ลองจินตนาการถึงสถานการณ์ที่คุณไม่สามารถควบคุมโค้ดที่เรียกว่าและคุณต้องการการประมวลผลแบบขนานโดยนัย

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.