Just algorithm!
มีอะไรใหม่ใน 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 มาเดี๋ยวนี้เลย Smiley

ส่วน Compiler as a Service
ก็ประมาณว่าเค้ายกเครื่อง C# Compiler ใหม่ทั้งหมด
แต่ก่อน Compiler ทำงานอย่างไงเราไม่สนใจ
แต่หลังจากนี้ เราสามารถถอดส่วนประกอบของโค้ดที่จะ Compile ได้ทั้งหมด

ผมคิดว่า ต่อจากนี้เราอาจได้เห็นอะไรแปลก ๆ มากขึ้น
ประมาณว่า สามารถ Log Exception ประเภทที่เก็บตัวแปรจาก method ได้
สร้าง Unit Test แบบ Full Coverage ได้
ทำการ Analyze Code และทำการ Refactor ให้อัตโนมัติ Smiley

จบครับ Smiley


Create Date : 16 มกราคม 2554
Last Update : 16 มกราคม 2554 3:55:26 น. 5 comments
Counter : 2488 Pageviews.

 
ขอบคุณครับ


โดย: ... IP: 27.130.87.181 วันที่: 16 มกราคม 2554 เวลา:8:31:17 น.  

 
สุดยอด


โดย: Se7en IP: 182.52.86.216 วันที่: 17 มกราคม 2554 เวลา:9:02:25 น.  

 
ชอบคุณครับ ติดตามอยู่เรื่อย


โดย: แอบ IP: 110.169.65.13 วันที่: 26 กุมภาพันธ์ 2554 เวลา:21:22:06 น.  

 
Happy birthday ka

ขอให้มีความสุขมากๆ สุขภาพแข็งแรง ร่ำรวยๆ และได้เป็นที่รักของทุกๆคนนะคะ


โดย: Sugar lip วันที่: 23 กรกฎาคม 2554 เวลา:0:24:44 น.  

 
ขอบคุณครับ คุณ Sugar lip


โดย: chaowman วันที่: 23 กรกฎาคม 2554 เวลา:0:44:07 น.  

ชื่อ :
Comment :
  *ใช้ code html ตกแต่งข้อความได้เฉพาะสมาชิก
 

chaowman
Location :
กรุงเทพฯ Thailand

[Profile ทั้งหมด]

ฝากข้อความหลังไมค์
Rss Feed
Smember
ผู้ติดตามบล็อก : 8 คน [?]





New Comments
Group Blog
 
All Blogs
 
Friends' blogs
[Add chaowman's blog to your web]
Links
 

 Pantip.com | PantipMarket.com | Pantown.com | © 2004 BlogGang.com allrights reserved.