มีอะไรใหม่ใน C#5.0
2 ปีที่แล้ว ผมเพิ่งเขียนบทความเกี่ยวกับ C#4.0 ตอนนี้ C#5.0 กำลังออกมาอีกละ
ผมมีโอกาสได้ดู Video เกี่ยวกับ C#5.0 มาสักพักใหญ่ แต่คิดว่ายังไม่สายไป หลายคนยังไม่รู้ วันนี้เลยเอามาบอกกล่าวเล่ากันครับ
ก่อนอื่น Download ไฟล์ presentation ไปดูประกอบกันก่อนครับ
ก่อนอื่นย้อนเวลาคร่าว ๆ C#1.0 คือ จุดเริ่มต้นของภาษา C แบบ Managed Code C#2.0 หลัก ๆ ก็ Generics C#3.0 Linq กับพรรคพวก (อ่านเพิ่มที่นี่) C#4.0 Dynamic (อ่านเพิ่มที่นี่)
และ C#5.0 ตอนนี้ส่วนใหญ่จะเป็นเรื่อง async กับ Compiler as a services มานิดหน่อย วันนี้เรามาดูกัน
ตัวอย่างผมเอามาจาก CTP นะครับ
สมมติคุณเขียนโปรแกรมสำหรับค้นหาหนังในปีต่าง ๆ คุณอาจจะสร้างปุ่มมาหนึ่งปุ่ม ปุ่มนั้นมีคำสั่งตามนี้ var first = 0; var pageSize = 10; while (true) { var movies = QueryMovies(year, first, pageSize); if (movies.Length == 0) break; DisplayMovies(movies); first += movies.Length; } จากโค้ดก็ง่าย ๆ สั่งค้นหาหนังไปเรี่อย ๆ ทีละ 10 เรื่อง แล้วก็แสดงออกมา แต่ปัญหาคือ ถ้าเขียนอย่างนี้หน้าจอจะ Freeze ไม่ขยับจนกว่าจะ Download หนังเสร็จทั้งหมด
วิธีแก้ปัญหานี้ หากเป็น C#4.0 คุณอาจจะใช้ BackgroundWorker, หรือวิธีอื่น ๆ ก็แล้วแต่ คุณต้องแก้ Logic ของโค้ด จากที่อ่านง่าย ๆ ก็เป็นอ่านไม่รู้เรื่อง
C#5.0 มีวิธีแก้ง่าย ๆ แค่คำว่า async กับ await async กับ await 2 คำนี้ใช้ด้วยกันเสมอ async ใช้ตอนประกาศ method บอกว่า method นี้จะมีการใช้ await ส่วน await ใช้เพื่อบอกว่า ให้รอ แต่ระหว่างรอไปทำอย่างอื่นก่อนก็ได้
โค้ดแก้ใหม่เป็นอย่างนี้ var first = 0; var pageSize = 10; var background = new SynchronizationContext(); while (true) { await background.SwitchTo(); var movies = QueryMovies(year, first, pageSize); await Application.Current.Dispatcher.SwitchTo(); if (movies.Length == 0) break; DisplayMovies(movies); first += movies.Length; }
แค่เพิ่มบรรทัดที่ขีดเส้นใต้เข้าไป กับคำว่า async ที่หัว method ไม่ต้องแก้โค้ดใด ๆ ทั้งสิ้น await ตัวแรกบอกให้ Thread UI รอ แต่ระหว่างรอจะทำอะไรอย่างอื่นก่อนก็ได้ ดังนั้น หน้าจอ UI จะไม่ Freeze จะย่อขยาย กดอะไรต่อก็ได้ตามสบาย background.SwitchTo เป็นการสั่งให้ย้ายไป Thread background ดังนั้นคำสั่ง QueryMovies จะทำที่ Thread background
เมื่อ Thread background ทำคำสั่ง QueryMovies เสร็จ ก็เจอ await ตัวที่ 2 บอกว่าให้ Thread background รอ Thread UI ที่ก็สลับกลับมาทำต่อจากเดิม ทำ method ชื่อ DisplayMovies เพื่อแสดงหนังบนหน้าจอ
พอ loop อีกหนึ่งรอบก็สลับเป็น Thread background ใหม่ เพื่อดึงข้อมูลหน้าถัดไป ทำอย่างนี้ไปเรื่อย ๆ จนจบ
เห็นไหมครับหลักการไม่มีอะไรเลย ไม่ต้องเปลี่ยนโค้ด แถมจะ Debug ก็ง่าย run เหมือนปกติ
ทีนี้ถ้าคุณอยากให้โค้ดคุณ advance มากขึ้น ไม่ต้องไปกำหนดว่า คำสั่งไหน run background อันไหน run UI
คุณก็อาจต้องแก้ method นิดหน่อย โดยปกติ method QueryMovies อาจมี Signature ตามนี้
Movie[] QueryMovies(int year, int start, int pageSize);
ก่อนทำอะไร มาทำความรู้จักกับ keyword async เพิ่มอีกนิดหน่อย ถ้าประกาศ async เราสามารถคืนค่าได้ 3 แบบ
async void async Task และ async Task<T>
method ที่ประกาศ async void ก็คือ method ธรรมดา เพียงแต่ใน method จะมีคำว่า await อยู่ข้างใน คนอื่นจะมารอ method ที่ประกาศ async void ไม่ได้
async Task ก็คือ method ที่คนอื่นจะมารอได้ แต่ไม่รับค่าใด ๆ และ async Task<T> คือ method ที่คนอื่นจะมารอรับค่า T กลับไป
ในกรณี method QueryMovies มีการคืนค่าจึงต้องแก้เป็น
async Task<Movie[]> QueryMovies(int year, int start, int pageSize);
ส่วนเนื้อหา method QueryMovies ส่วนที่สั่ง Download ข้อมูล Microsoft เค้าจะเตรียม Library บางส่วนที่เป็น async ไว้ให้ ซึ่งมีคำสั่งสลับ Thread ให้อยู่แล้ว
เช่น ปกติเวลา Download สั่ง var data = client.DownloadString(new Uri(url));
ก็เปลี่ยนเป็น var data = await client.DownloadStringTaskAsync(new Uri(url));
ส่วนการคืนค่า ก็ return เป็น Movie[] ตามปกติ ไม่ต้องแก้อะไร .NET มันจะแปลงเป็น Task<Movie[]> ให้เอง สำหรับ method ที่เป็น async
ทีนี้การรอคำสั่ง QueryMovies ก็ง่ายขึ้นเยอะ สามารถเขียนเป็นแบบนี้ได้
var first = 0; var pageSize = 10; while (true) { var movies = await QueryMovies(year, first, pageSize); if (movies.Length == 0) break; DisplayMovies(movies); first += movies.Length; }
เขียนแทบจะเหมือนเดิม เติมแค่คำว่า await เข้าไป มันง่ายจริง ๆ จนอยากให้มันออก C#5.0 มาเดี๋ยวนี้เลย
ส่วน Compiler as a Service ก็ประมาณว่าเค้ายกเครื่อง C# Compiler ใหม่ทั้งหมด แต่ก่อน Compiler ทำงานอย่างไงเราไม่สนใจ แต่หลังจากนี้ เราสามารถถอดส่วนประกอบของโค้ดที่จะ Compile ได้ทั้งหมด
ผมคิดว่า ต่อจากนี้เราอาจได้เห็นอะไรแปลก ๆ มากขึ้น ประมาณว่า สามารถ Log Exception ประเภทที่เก็บตัวแปรจาก method ได้ สร้าง Unit Test แบบ Full Coverage ได้ ทำการ Analyze Code และทำการ Refactor ให้อัตโนมัติ
จบครับ
Create Date : 16 มกราคม 2554 |
Last Update : 16 มกราคม 2554 3:55:26 น. |
|
5 comments
|
Counter : 2488 Pageviews. |
|
|