เพียงแค่มี VS2012 async
และพยายามที่จะได้รับการจัดการใน
สมมติว่าฉันมีวิธีการดึงค่าจากแหล่งที่มาของการบล็อก ฉันไม่ต้องการให้ผู้โทรของเมธอดบล็อก ฉันสามารถเขียนเมธอดในการโทรกลับซึ่งจะเรียกใช้เมื่อค่ามาถึง แต่เนื่องจากฉันใช้ C # 5 ฉันจึงตัดสินใจที่จะทำให้เมธอด async เพื่อให้ผู้โทรไม่ต้องจัดการกับการโทรกลับ:
// contrived example (edited in response to Servy's comment)
public static Task<string> PromptForStringAsync(string prompt)
{
return Task.Factory.StartNew(() => {
Console.Write(prompt);
return Console.ReadLine();
});
}
นี่คือตัวอย่างวิธีการที่เรียกมัน ถ้าPromptForStringAsync
ไม่ใช่ async วิธีนี้จะต้องมีการซ้อนการโทรกลับภายในการโทรกลับ ด้วย async ฉันจะเขียนวิธีการของฉันด้วยวิธีที่เป็นธรรมชาตินี้:
public static async Task GetNameAsync()
{
string firstname = await PromptForStringAsync("Enter your first name: ");
Console.WriteLine("Welcome {0}.", firstname);
string lastname = await PromptForStringAsync("Enter your last name: ");
Console.WriteLine("Name saved as '{0} {1}'.", firstname, lastname);
}
จนถึงตอนนี้ดีมาก ปัญหาคือเมื่อฉันเรียก GetNameAsync:
public static void DoStuff()
{
GetNameAsync();
MainWorkOfApplicationIDontWantBlocked();
}
จุดรวมของGetNameAsync
มันคืออะซิงโครนัส ฉันไม่ต้องการให้บล็อกเพราะฉันต้องการกลับไปที่ MainWorkOfApplicationIDontWantBlocked ASAP และปล่อยให้ GetNameAsync ทำในพื้นหลัง อย่างไรก็ตามการเรียกมันด้วยวิธีนี้ทำให้ฉันมีคำเตือนเกี่ยวกับคอมไพเลอร์ในGetNameAsync
บรรทัด:
Warning 1 Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
ฉันทราบดีว่า "การดำเนินการของวิธีการปัจจุบันยังคงดำเนินต่อไปก่อนที่การโทรจะเสร็จสมบูรณ์" นั่นคือจุดของรหัสอะซิงโครนัสใช่ไหม?
ฉันชอบให้โค้ดของฉันคอมไพล์โดยไม่มีคำเตือน แต่ไม่มีอะไรต้อง "แก้ไข" ที่นี่เพราะโค้ดทำในสิ่งที่ฉันตั้งใจจะทำ ฉันสามารถกำจัดคำเตือนได้โดยเก็บค่าส่งคืนของGetNameAsync
:
public static void DoStuff()
{
var result = GetNameAsync(); // supress warning
MainWorkOfApplicationIDontWantBlocked();
}
แต่ตอนนี้ฉันมีรหัสที่ไม่จำเป็น Visual Studio ดูเหมือนจะเข้าใจว่าฉันถูกบังคับให้เขียนโค้ดที่ไม่จำเป็นนี้เนื่องจากมันระงับคำเตือน "ค่าไม่เคยใช้" ปกติ
ฉันยังสามารถกำจัดคำเตือนได้โดยการตัด GetNameAsync ด้วยวิธีการที่ไม่ใช่ async:
public static Task GetNameWrapper()
{
return GetNameAsync();
}
แต่นั่นคือรหัสที่ไม่จำเป็นยิ่งไปกว่านั้น ดังนั้นฉันต้องเขียนโค้ดฉันไม่ต้องการหรือยอมรับคำเตือนที่ไม่จำเป็น
มีบางอย่างเกี่ยวกับการใช้ async ของฉันที่ผิดที่นี่หรือไม่?
PromptForStringAsync
คุณจะทำงานได้มากกว่าที่คุณต้องการ เพียงแค่ส่งคืนผลลัพธ์ของTask.Factory.StartNew
. เป็นงานที่มีค่าเป็นสตริงที่ป้อนในคอนโซลอยู่แล้ว ไม่จำเป็นต้องรอให้ผลลัพธ์กลับมา การทำเช่นนั้นจะไม่เพิ่มมูลค่าใหม่