async รองานส่งคืน


132

ใครสามารถอธิบายความหมายของวิธีการซิงโครนัสได้บ้าง ถ้าลองเปลี่ยนวิธีเป็นasyncVS ก็บ่นไปเลย

ใช้งานได้:

public Task MethodName()
{
     return Task.FromResult<object>(null);
}

สิ่งนี้ใช้ไม่ได้:

public async Task MethodName()
{
     return Task.FromResult<object>(null);
}

โดยพื้นฐานแล้วฉันต้องการทราบว่านี่หมายถึงอะไร: Task.FromResult<object>(null);


1
นอกจากนี้อ่าน MSDN: msdn.microsoft.com/en-us/library/hh194922(v=vs.110).aspx
Patrick Hofman

@LB อืมได้ผล! แต่ถ้าฉันแค่return;ทำงานด้วย ... !
David Dury

2
"ใช้งานไม่ได้" ไม่ได้ให้คำอธิบายที่ดีมากเกี่ยวกับสิ่งที่ใช้งานไม่ได้ ข้อความแสดงข้อผิดพลาดที่คุณได้รับคืออะไร?
John Koerner

@JohnKoerner ฉันคิดว่ามันค่อนข้างชัดเจนว่าคอมไพเลอร์อาจให้ข้อผิดพลาดเหมือนกับว่าคุณพยายามส่งคืนค่าในvoidฟังก์ชัน
binki

คำตอบ:


238

asyncวิธีการแตกต่างจากวิธีการปกติ ไม่ว่าคุณจะกลับมาจากasyncวิธีการใดก็ตามจะห่อด้วยไฟล์Task.

หากคุณไม่ส่งคืนค่า (เป็นโมฆะ) จะถูกห่อไว้Taskหากคุณส่งคืนintจะถูกห่อด้วยTask<int>และอื่น ๆ

หากวิธีการ async ของคุณจำเป็นต้องส่งคืนintคุณจะต้องทำเครื่องหมายประเภทการส่งคืนของวิธีการเป็นTask<int>และคุณจะส่งคืนแบบธรรมดาintไม่ใช่Task<int>. คอมไพเลอร์จะแปลงไฟล์intให้Task<int>คุณ

private async Task<int> MethodName()
{
    await SomethingAsync();
    return 42;//Note we return int not Task<int> and that compiles
}

Sameway เมื่อคุณส่งTask<object>คืนประเภทผลตอบแทนของวิธีการของคุณควรเป็นTask<Task<object>>

public async Task<Task<object>> MethodName()
{
     return Task.FromResult<object>(null);//This will compile
}

เนื่องจากวิธีของคุณกำลังส่งคืนTaskจึงไม่ควรส่งคืนค่าใด ๆ มิฉะนั้นจะไม่รวบรวม

public async Task MethodName()
{
     return;//This should work but return is redundant and also method is useless.
}

เก็บไว้ในใจว่าวิธี async โดยไม่ต้องมีคำสั่งไม่ได้awaitasync


1
สำหรับฉันประเภทการส่งคืนนี้ใช้ไม่ได้ (ฉันเดาว่าฉันทำอะไรผิดพลาด) ตัวอย่าง static async Task <string> DoStuff () {... = await SomeMethodAsync (); ส่งคืน "ค่าสตริง"; } .. var x = DoStuff (); แต่ x - อยู่ในประเภท "Task <string>" ไม่ใช่กับ type "string" ... ทำไมถึงเป็นเช่นนั้น?
Prokurors

3
@Prokurors คุณต้องรอDoStuff()ด้วย ตัวอย่าง:var x = await DoStuff();
Sriram Sakthivel

5
ควรจะเป็นreturn await Task.FromResult<object>(null);
sandeep talabathula

@sandeeptalabathula ที่เท่ากับ return null
Sriram Sakthivel

2
@ProfK Task.WhenAnyเป็นตัวอย่าง
Servy

56

คุณต้องใช้คีย์เวิร์ด await เมื่อใช้ async และประเภทการส่งคืนฟังก์ชันของคุณควรเป็นแบบทั่วไปนี่คือตัวอย่างที่มีค่าส่งคืน:

public async Task<object> MethodName()
{
    return await Task.FromResult<object>(null);
}

นี่คือตัวอย่างที่ไม่มีค่าส่งคืน:

public async Task MethodName()
{
    await Task.CompletedTask;
}

อ่านสิ่งเหล่านี้:

TPL: http://msdn.microsoft.com/en-us/library/dd460717(v=vs.110).aspxและงาน: http://msdn.microsoft.com/en-us/library/system.threading .tasks (v = vs.110) .aspx

Async: http://msdn.microsoft.com/en-us/library/hh156513.aspx รอ: http://msdn.microsoft.com/en-us/library/hh156528.aspx


9
คุณสามารถกลับnullโดยตรงแทนที่จะรองานหลอกๆ
Lee

5
@Lee แต่ถ้าคุณทำเช่นนั้นคอมไพเลอร์จะบ่น (ให้คำเตือน) ว่าasyncเมธอดจะดำเนินการแบบอะซิงโครนัสพร้อมคำแนะนำให้ใช้awaitคีย์เวิร์ดที่ใดที่หนึ่งในเมธอด ฉันขอแนะนำให้ใช้return Task.FromResult((object)null);และลบasyncคำสำคัญเพื่อลดเสียงเตือนของคอมไพเลอร์
binki

ใช่ฉันได้ลองใช้returnในงาน แต่งานยังคงดำเนินการต่อไปเพราะreturnไม่ส่งคืน aTask
Turner Bass

30

การเพิ่มคีย์เวิร์ด async เป็นเพียงแค่น้ำตาลในการสังเคราะห์เพื่อลดความซับซ้อนในการสร้างเครื่องสถานะ โดยพื้นฐานแล้วคอมไพเลอร์ใช้รหัสของคุณ

public async Task MethodName()
{
     return null;
}

และเปลี่ยนเป็น;

public Task MethodName()
{
     return Task.FromResult<object>(null);
}

หากรหัสของคุณมี awaitคีย์เวิร์ดคอมไพเลอร์จะต้องใช้เมธอดของคุณและเปลี่ยนเป็นคลาสเพื่อแสดงสถานะเครื่องที่จำเป็นในการรัน ในแต่ละawaitคีย์เวิร์ดสถานะของตัวแปรและสแต็กจะถูกเก็บรักษาไว้ในฟิลด์ของคลาสคลาสจะเพิ่มตัวเองเป็นฮุคที่สมบูรณ์ให้กับงานที่คุณกำลังรอจากนั้นจึงกลับมา

เมื่องานนั้นเสร็จสิ้นงานของคุณจะถูกดำเนินการอีกครั้ง ดังนั้นโค้ดพิเศษบางส่วนจะถูกเพิ่มไว้ที่ด้านบนของวิธีการเพื่อคืนค่าสถานะของตัวแปรและข้ามไปยังส่วนถัดไปของโค้ดของคุณ

ดูasync & await สร้างอะไรสำหรับตัวอย่างเลือด

กระบวนการนี้มีหลายอย่างเหมือนกันกับวิธีที่คอมไพลเลอร์จัดการกับเมธอดตัววนซ้ำด้วยคำสั่งผลตอบแทน


2

นี่คืองานที่ส่งคืนงานประเภท String (ฟังก์ชัน C # ไม่ระบุชื่อหรือในคำอื่น ๆ ใช้การมอบหมาย 'Func')

    public static async Task<string> MyTask()
    {
        //C# anonymous AsyncTask
        return await Task.FromResult<string>(((Func<string>)(() =>
        {
            // your code here
            return  "string result here";

        }))());
    }

1
เมื่อโพสต์รหัสเป็นคำตอบโปรดใส่คำอธิบายเกี่ยวกับสิ่งที่คุณกำลังสาธิต ในกรณีนี้คุณกำลังเพิ่มคำตอบสำหรับคำถามเก่าที่มีคำตอบอยู่แล้วหลายคำตอบ โปรดเพิ่มประโยคหรือสองประโยคที่อธิบายว่าคำตอบใหม่ของคุณแสดงให้เห็นถึงอะไรซึ่งยังไม่ปรากฏในคำตอบอื่น ๆ ฉันไม่ได้พูดอะไรผิดกับคำตอบของคุณเพียงแค่ขอให้คุณช่วยเหลือผู้อื่นโดยใส่คำที่คุณแสดงพร้อมกับรหัสของคุณ
ToolmakerSteve

0

เพื่อให้ได้รับการตอบกลับที่เหมาะสมจากวิธีการ async คุณต้องรอในขณะที่เรียกใช้วิธีการงานเหล่านั้น ซึ่งจะรอการแปลงกลับเป็นประเภทค่าที่ส่งคืนแทนที่จะเป็นประเภทงาน

เช่นเนื้อหา var = รอ StringAsyncTask (

โดยที่ Public async Task < String > StringAsyncTask ())

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