Question To me

หลังจากเขียนไปได้สักพักใหญ่ๆ มีคนเข้ามาอ่านเยอะ แล้วก็มีคำถามอยากจะถามผม แต่เนื่องจากไม่มี webboard และผมไม่อยากจะตอบคำถามทาง msn อะไรแบบนี้เท่าไหร่ เลยเขียนหน้า question-to-me มาแทนละกัน ดูตรง shotcut ก็ได้ครับ ทำ link ไว้ให้แล้ว ถ้าหากมีคำถามอะไร ที่เกี่ยวกับเขียนโปรแกรม หรืออาจจะไม่เกียว ก็จะได้ไปถามหน้านั้นเลย สรุปง่ายๆว่าโพสมันลงไปที่หน้านั้นนั่นเหละ ถ้าผมตอบได้ก็จะตอบน่ะครับ แต่อาจจะช้านิดหนึง

จริงๆผมก็คิดไว้น่ะว่า จะทำเป็นเวปเลยดีไม๊ แต่ก็กลัวว่าจะดูแลไม่ไหว – -*

อีกอย่างคิดชื่อ โดเมน ไม่ออกว่าจะชื่อว่าอะไรดี

แต่ถ้าจะทำเมื่อไหร่่ ผมจะบอกอีกทีนะครับ

เดือนหน้าเริ่ม cocoa แล้วครับ เย้ๆๆๆๆๆๆ

Ojective-C Programming – Copying Object

นี่ก็น่าจะเป็นเรื่อง objective-c แบบเพียวๆเกือบๆจะสุดท้ายละ ก็เหลืออีกไม่กี่เรื่องที่ผมคิดว่าน่าจะเพียงพอสำหรับการเริ่มต้นกับ cocoa เอาละเข้าเรื่องเลยดีกว่า

โดยปกติเราเวลาที่เราประกาศตัวแปรขึ้นมาสักตัว ถ้าไม่ใช่ class ก็จะเป็น primitive type เป็นต้นว่า int , char , double การที่เราจะ copy ข้อมูลจาก ตัวแปรหนึ่งไปยังอีกตัวแปร หนึ่งนั้นทำได้ง่ายมาก เพียงแค่ใช้เครื่องหมาย = แค่นี้เองเช่นเป็นต้นว่า

จาก code เบื้องต้นจะเห็นว่า

  • บรรทัดที่ 3 เราได้ให้ b มีค่าเท่ากับ a
  • บรรทัดที่ 4 เพิ่มค่า a ด้วย 15
  • บรรทัดที่ 5 เพิ่มค่า b ด้วย 10
  • แน่นอนว่า จาก code ข้างบนนี้ ค่า a กับ b มีค่าต่างกันคือ 20 กับ 25
  • สรุปง่ายๆว่า เราได้ให้ค่า b เท่ากับ ค่า a ในบรรทัดที่ 3 แต่เมื่อเราเปลี่ยนค่า a ในบรรทัดที่ 4 ก็ไม่ได้มีผลกระทบอะไรกับค่า b
  • และในทำนองเดียวกัน ถ้าเราทำการแก้ไขค่าของ a ก็ไม่ได้มีผลอะไรกับ b

แต่การประกาศ class instance นั้นถ้าเราเขียนโปรแกรมในลักษณะเหมือนๆกับ ข้างบน ดังเช่นตัวอย่างข้างล่าง

จาก code ข้างบน

  • เราได้ประกาศ instance ของ NSMutableString มา 2 ตัวคือ hello กับ temp
  • ในบรรทัดที่ 8 และเราก็ได้ให้ ค่า temp มีค่าเท่ากับ hello นั่นก็แปลว่า temp ควรจะมีค่า เป็น Hello
  • จากนั้นในบรรทัดที่ 9 เราก็ได้เปลี่ยนแปลงค่า ของ temp โดยการต่อท้ายด้วย World
  • และบรรทัดที่ 10 เราก็ให้พิมพ์ค่าตัวแปร hello ออกมา
  • แต่ผลปรากฎว่า มันกลับพิมพ์คำว่า Hello World ออกมา ทั้งๆที่เราก็ไม่ได้ไปทำการแก้ไขค่าใน ตัวแปร hello เลยสักนิด

ทำไมถึงเป็นแบบนี้ ?

เพราะว่า การประกาศ class instance นั้นเป็นการประกาศ pointer ( คือตัวแปรที่เก็บค่าของตำแหน่ง memory ) ของ class นั้นๆ ฉนั้นการที่เขียน code ว่า

temp = helloString

ก็เป็นการบอกว่า ให้ temp นั้นชี้ไปยังตำแหน่ง memory เดียวกันกับ hello ฉนั้นแล้วเมื่อมันเป็น ตำแหน่ง memory เดียวกัน ถ้าหากเราทำการแก้ไข temp จึงทำให้ hello ต้องเปลี่ยนไปด้วย

เหมือนในภาษา c/c++ถ้าดู code ต่อไปนี้

การที่เราเขียน code แบบนี้เป็นการให้ temp ชี้ไปที่ตำแหน่ง memory ของ hello ไม่ได้เป็นการ copy ค่า ( เราต้องการให้ temp มีค่าเป็นคำว่า Hello World!! ) ฉนั้นแล้วเมื่อเราสั่ง printf ตัวแปร temp ออกมาก็จะไม่ได้คำว่า Hello World!! เพราะเป็นการชี้ตำแหน่ง memory ไปยังตำแหน่งใหม่ ถ้าหากเราจะ ให้ค่า temp เป็น Hello World เหมือนกับ hello เราต้องใช้ ฟังชั่นที่ชื่อว่า strcpy ทำการ copy string ถ้าเป็นภาษา c/c++ อาจจะเขียนได้แบบนี้

ปล. ใครที่ยังไม่เข้าใจเรื่อง pointer ให้ไปอ่านเพิ่มเติมน่ะครับ เดี๋ยวจะงง
http://www.vcharkarn.com/vlesson/showlesson.php?lessonid=1&pageid=7

แล้วเราจะ copy มันได้ยังไง ?

ใน Foundation class นั้นจะมี method ที่ชื่อว่า copy และ mutableCopy เพื่อให้เราสามารถ clone ค่าจาก instance หนึ่งไปยังอีก instance หนึ่งได้ และสอง method นี้ต่างกันกันตรงที่ว่า ถ้าเป็นหากเราต้องการจะคัดลอกไปแล้วให้มันแก้ไขได้ ก็ต้องใช้ mutableCopy ( สำหรับ mutable object นั้นก็ควรจะใช้ mutableCopy )

มาดูกันว่าจากข้างบนเราจะเปลี่ยนให้ temp มันเท่ากับ helloString ได้ยังไง

ถ้าเรา compile และ run ดูจะเห็นว่าผลลัพธ์ที่ได้จะออกมาเป็น

Hello
HelloWorld

ซึ่งจะต่างจากโปรแกรมแรกที่เราเขียน เพราะว่า เราทำการ copy ค่าจาก helloSting มาให้ยัง temp ( การ copy ในที่นี้หมายถึงการคัดลอกข้อมูลในตำแหน่ง memory ที่ต้องการไปยังอีกที่) นั่นก็แปลว่าค่าของตัวแปรทั้งสองอันนี้แยกจากกัน ฉนั้นถ้าเราแก้ไขตัวแปร temp ก็ไม่ได้เกี่ยวอะไรกับ helloString

Shallow – Deep

อย่างที่บอกไปแล้วว่า instance นั้นคือ pointer ดีๆนี่เอง ลองพิจารณา code ข้างล่างนี้

จากโปรแกรมข้างบน

    เราเริ่มด้วยการประกาศตัวแปรมาทั้ง 3 ตัวคือ arrayOne arrayTwo และ helloString

  • หลังจากนั้น เราก็ได้เอาตัวแปร helloString ไปเก็บไว้ที่ arrayOne
  • จากนั้นก็ arrayTwo ก็ได้ mutableCopy จาก arrayOne
  • สรุปว่า ตอนนี้ arrayOne มี member 1 ตัวคือ helloString ส่วน arrayTwo ก็มี member 1 ตัวเหมือนกันเพราะว่าไปก๊อปจาก arrayOne มา
  • หลังจากนั้นเราได้ทำการแก้ไข ค่าของ member ใน arrayTwo โดยเพิ่มคำว่า World เข้าไป
  • สุดท้ายเราพิมพ์ค่าของ arrayOne ออกมาร แต่ผลที่ได้คือ มันพิมพ์คำว่า Hello World !!!!
  • อ้าวทำไมมันเป็นแบบนี้ละ ทั้งๆที่เราแก้ไขตัวแปร ใน arrayTwo แล้วมันเกี่ยวอะไรกับ arrayOne ?

    จริงอยู่ครับว่า arrayTwo นั้นก๊อปปี้ arrayOne มา นั่นก็แปรได้ว่ามันใช้ memory คนละส่วนกันแล้วดังนั้นมันก็ควรจะไม่เกี่ยวกัน ก็ถูกต้องแล้วละครับ ว่ามันไม่ได้เกียวกันการแก้ไข member ใน arrayOne ก็ไม่ได้เกียวกับ arrayTwo

    แต่เผอิญว่า ตัวแปร ที่ arrayOne นั้นเก็บไว้มันเป็น pointer ที่ชี้ไปยัง helloString นั่นก็แปลได้ง่ายๆว่า member ใน array นั้นไม่ได้ถูก clone มาด้วย เป็นแค่การ copy reference มาแค่นั้น ฉนั้นการแก้ไข ตัวแปรใน arrayOne ย่อมมีผลกระทบต่อ arrayTwo สิ่งที่มันเป็นลักษณะ นี้เรียกว่า shallow copy

    แล้วจะทำยังไงให้มันแยกขาดจากกันเลย ?

    คำตอบคือ เราต้อง ทำเองครับ เพราะว่ามันไม่ได้ทำให้เรา แต่จะทำยังไงละ ?

    Copying Class Instance

    จริงอยู่ว่าเราสามารถใช้ copy , mutableCopy ได้แต่ถ้าหากเป็น class ที่เราเขียนขึ้นมาเองนั้นไม่สามารถทำได้ เราต้องเขียนเองเหมือนกัน

    สรุปว่าตอนนี้ก็มีตัวอย่างที่เราต้องทำเอง ถึง 2 เคสด้วยกัน วิธีการก็ไม่ได้ยากเย็นอะไรนัก เราเพียงแค่ implement interface <NSCopy> หรือ <NSMutableCopy> เท่านั้นเอง มาดูกันเลยดีกว่า ว่ามันหน้าตาเป็นยังไง

    ก็ดูจาก code ข้างบนจะเห็นว่า ตอนที่ประกาศ class จะมีส่วนเพิ่มเติมเข้ามาคือ <NSCopying> เมื่อเรามี interface NSCopying แล้วสิ่งที่ต้องทำต่อมาก็คือ implement ส่วนของ method ที่มีชื่อว่า -(id) copyWithZone: (NSZone*) zone แล้วภายใน method ก็ประกาศตัวแปร และก็ copy ค่าต่างๆมาให้ยัง object ใหม่ที่ทำการประกาศ เพียงเท่านี้ก็เสร็จ แล้วครับ

    ลอง compile และ run ดูจะเห็นว่า myclass_B นั้นมีค่าเหมือนกับ myclass_A ทุกอย่าง

    งงตรงไหน ติชม คอมเม้นกันมาได้นะครับ

Ojective-C Programming – Thread II

หลังจากเขียน Thread พอเป็นแล้วก็ยังมีเรื่องเกี่ยวกับ Thread ที่ต้องรู้อีก อยู่อย่างหนึ่งก็คือ การ Synchronizes ระหว่าง Thread

อย่างที่บอกไปแล้ว ว่าการเขียนโปรแกรมโดยการใช้ Thread นั้นมีข้อดีมากมาย แต่ก็มีข้อเสียเหมือนกัน และหนึ่งในข้อเสียนั้นก็คือการเขียนโปรแกรมแบบที่มีหลายๆ thread นั้นทำให้โปรแกรมของเราซับซ้อนมากขึ้น และลำบากต่อการจัดการข้อมูลที่มีการใช้งานร่วมกันระหว่าง thread เช่นเป็นต้นว่า

ถ้าโปรแกรมที่เราเขียนขึ้นมีหลายๆ Thread โดยแต่ละ Thread นั้นมีการแชร์ข้อมูลร่วมกัน ถ้าหากเราไม่ได้เขียนโปรแกรมให้มันมีการควบคุมการทำงานของแต่ละ Thread หรือเขียนได้ไม่ดี อาจจะเกิดเหตการณ์ในลักษณะแบบนี้

สมมติว่า โปรแกรม ของเรามี 2 thread ที่มีการใช้ตัวแปรร่วมกันคือ Money และแต่ละ thread นั้นก็จะทำการอ่านค่า Money และเขียนผลลัพธ์ที่ได้จากการคำนวนใหม่ลงไป

  1. Thread A : อ่านตัวแปร Money ได้มีค่าเป็น 10$ และระหว่างการคำนวนนี้ ใช้เวลาประมาณ 10 นาโนวินาที
  2. และระหว่างที่ A กำลังคำนวนอยู่นั้น Thread B ก็ได้อ่านค่า Money เหมือนกัน ได้ค่า 10$ เหมือนกัน แต่ใช้เวลาในการคำนวนเพียงแค่ 5 นาโนวินาที
  3. เนื่องจาก ว่า B นั้นทำงานเสร็จก่อน A ถึง 5 นาโนวินาที. Thread B จึงทำการ เขียนค่า Money เข้าไปใหม่เป็น 30$
  4. เมื่อ A ทำงานเสร็จ A ก็เลยเขียนค่า Money ที่ได้จากการคำนวนใหม่เป็น 15$

**** จะเห็นว่าค่าผลลัพธ์ที่ได้นั้น มันเกิดการ เขียนทับกันขึ้นมา ลองจินตนาการว่า สมมติว่า มี คนสองคนทำการฝากเงิน ในเวลาพร้อมๆกัน เข้าบัญชีเดียวกัน ขณะที่นาย A กำลังฝากเงินต้องใช้เวลาในการประมวลเสร็จใช้เวลา 10 วินาทีและในระหว่างนี้ นาย B ก็ฝากเงินมาเหมือนกัน แต่ใช้เวลา 5 วินาที ถ้าหากเราไม่มีการจัดการตรงนี้ นั่นก็แปรว่า เมื่อข้อมูลในบัญชี update จากการฝากเงินของ B ก็จะถูกเขียนทับด้วย ข้อมูลใหม่ที่นาย A ได้ฝากเข้ามา นันก็แปลว่า ข้อมูลเงินฝากนั้นผิดพลาด สิ่งที่ควรจะเป็นก็คือ ต้องรอให้ A ทำงาน เสร็จก่อน แล้ว B จึงอ่านข้อมูล ****

ลองมาเขียนโปรแกรมสักโปรแกรม โดยโปรแกรมนี้มี 2 Thread โดยที่
thread เป็นการเพ่ิมจำนวน member ใน array, ส่วนอีก thread นั้นทำหน้าที่ดึงข้อมูลจาก array แล้วทำการเปลี่ยนแปลงค่า

ลองดูโปรแกรม ข้างล่างนี้

และจากการ Compile & Run โปรแกรม ผลลัพธ์ที่ได้จะมีเป็นประมาณนี้

0 Hello World!!
1 hello World!!
.
.
8 Hello World!!
9 Hello World!!
10 Hello World!! World!!
11 Hello World!! World!!
12 Hello World!! World!!
13 Hello World!! World!!
14 Hello World!! World!!
15 Hello World!!
16 Hello World!!
17 Hello World!!
18 Hello
.
.
98 Hello
99 Hello

จากผลลัพธ์จะเห็นว่า เนื่องจาก Thread ทั้งสองคือ thread ที่เรียกใช้งาน AddMember ที่ทำหน้าที่เพิ่มจำนวน member ใน m_array  และ อีก thread ทำหน้าที่ AddMoreText ทำหน้าที่เรียกใช้ ตัวแปร m_array และแก้ไขค่า ในแต่ละ member ของ m_array ซึ่งสอง thread ทำงานแยกจากกันและเริ่มทำงานพร้อมกัน

ดังนั้น ในขณะที่ Thread ทั้งสองทำงานและมีการใช้งานข้อมูลร่วมกัน โดยไม่มีการ synchronize ข้อมูลระหว่างกันว่า m_array ว่าตอนนี้ข้อมูลเป็นอย่างไร จึงเป็นเหตุทำให้โปรแกรมทำงานผิดพลาดได้ ( มันควรจะเป็น Hello World!! ทั้งหมด ไม่ใช่ Hello World!! World!! หรือ Hello อย่างเดียว )

วิธีการแก้ปัญหา หรือป้องกัน สิ่งที่เกิดขึ้น มักนิยมใช้ คือ การ Lock ตัวแปร หรือ code ให้ทำงานได้ทีละ Thread เพื่อกันไม่ให้ Thread อื่นๆเข้าใช้จนกว่าจะใช้งานเสร็จ

NSLock

เราจะใช้ class ที่ชื่อ NSLock เพื่อจะเข้ามาช่วยในการจัดการ การทำงานของแต่ละ thread โดยมันจะทำหน้าที่ lock code ในส่วนที่ต้องการให้สามารถเข้าทำงานได้ทีละ Thread ไว้ ส่วน thread อื่นๆ ก็ต้องทำการรอ จนกว่า จะมีการ unlock เกิดขึ้น

การใช้งาน NSLock นั้น ก็เพียงแค่ประกาศ NSLock ขึ้นมา และเรียกใช้ lock หรือ unlock เท่านั้นเอง

จากตัวอย่าง code ข้างบน ก็แก้ไข ส่วนของ interface โดยการเพิ่มตัวแปร NSLock และในส่วนของ method ก็ทำการ เรียกใช้ lock และ unlock

ส่วน Method ก็ทำการแก้ไขได้เป็น

เพียงเท่านี้ก็แก้ปัญหาได้แล้ว สำหรับผลลัพธ์ ที่่ออกมาก็คือ

0 Hello World!!
1 Hello World!!
.
.
98 Hello World!!
99 Hello World!!

จะเห็นว่า จะไม่เกิดการซ้อนทับ เหมือนกับ ตัวอย่างแรก

@synchronized

ยังมีอีกวิธี ที่สามารถทำการ lock ในส่วนที่ต้องการได้ ถ้าไม่ต้องการใช้ NSLock เราเพียงแค่เขียน code ที่ต้องการจะ lock ไว้ภายในส่วนของ @synchronized { } ก็ทำได้เหมือนกัน

เป็นต้นว่า

ก็ติดปัญหาอะไร ถามได้น่ะครับ

Ojective-C Programming – Thread

ก็ยังคงต่อเนื่องด้วย Objective-C เหมือนเดิม ว่าจะขึ้น cocoa มา 3 รอบแล้วก็ยังไม่ได้ขึ้นสักที บอกตั้งแต่ iPhone SDK เพิ่งจะออกจนตอนนี้มันเป็น Beta 6 ไปละ หวังไม่โกรธกันนะครับ เอาละวันนี้เข้าเรื่องเลยดีกว่า

Thread

คืออะไร ?  ก็อธิบายได้ง่ายๆว่า มันคือส่วนย่อยๆของ Process หรือชุดคำสั่งนั่นเหละ โดยทำงานแยกจากกัน โดยปกติแล้วโปรแกรมที่เขียนขึ้นมาง่ายๆมักจะเป็นลักษณะ 1 thread หรืออาจจะเรียกได้ว่า “Single Thread” ถ้ามีหลายๆ thread ก็เรียกว่า “Multithread” สำหรับโปรแกรมใหญ่ๆแล้วจะมีการใช้ thread มากกว่า 1

การใช้งาน thread มีข้อดีหลายอย่างตั้งแต่ การใช้ทรัพยาการร่วมกัน การสนับสนุนการทำงานของ multiprocessor และอื่นๆอีกมากมาย สำหรับใครที่ไม่เคยรู้เรื่อง thread นั้นแนะนำให้ไปอ่านเพิ่มเติม

http://www.thaiall.com/os/os04.html

http://en.wikipedia.org/wiki/Thread_(computer_science)

เมื่อพอเข้าใจเบื้องต้นแล้ว เข้าสู้เนื้อหาของเราเลยดีกว่า ว่าเราจะสร้าง Thread และใช้งานมันได้อย่างไร

NSThread

ใน objective-c นั้นสามารถทำได้ตั้งแต่การเรียกใช้ thread ของ ภาษา c เช่น pthread แต่ไหนๆเราจะเขียน objective-c กันแล้ว จะไปใช้ pthread กันทำไม เพราะใน objective-c เองนั้นก็มี class ที่อำนวยความสะดวกในการสร้าง thread อยู่แล้วนั่นคือ NSThread

การสร้าง thread นั้นทำได้ อยู่ 2 วิธีคือ

  • เรียกใช้ class method ที่มีชื่อว่า detachNewThreadSelector:toTarget:withObject:

การสร้าง thread ด้วย detachNewThreadSelector แบบนี้เราไม่จำเป็นต้องประกาศ ตัวแปรอะไรเลย จะมีก็แต่ parameter ที่ต้องใส่เข้าไป มาดูการประกาศ thread อีกแบบกันเลย

  • สร้าง NSThread ขึ้นมาแล้วเรียก start

ส่วนแบบวิธีนี้ต่างจากอันแรกคือ เราสร้างตัวแปร NSThread ขึ้นมาแล้วก็ใส่ค่า parameter ให้กับมัน หลังจากนั้นก็เรียก start สำหรับการสร้างแบบนี้มีข้อดี ต่างจากอย่างแรกก็คือ เราสร้างไว้ก่อนแล้วค่อยเรียกให้ thread start ทีหลังได้

ก็หลังจากสร้างเป็นแล้ว มาดูการใช้งาน กันเลยดีกว่า

สมมติว่า เราจะเขียนโปรแกรม ที่เอาไว้เขียน console แบบง่ายๆกัน แต่เป็นแบบ หลายๆ thread

จากโปรแกรม ข้างบน อธิบายคร่าวๆนะครับว่า เราประกาศ  class ชื่อ Console ขึ้นมาโดยที่มี method  เพียงแค่ PrintToConsole โดยการทำงานของ method นี้ก็คือให้พิมพ์ข้อความทั้งหมด 5 ครั้ง

หลังจากนั้นก็ทำการประกาศ ตัวแปร Console ขึ้นมาอีก 3 โดยแต่ละ object นั้นก็ทำการพิมพ์ข้อความออกมาไม่เหมือนกันนั่นก็คือ Hello , Sample , Ok

ลำดับต่อไปก็ทำการ สร้าง Thread ขึ้นมา โดยจากตัวอย่าง ผมได้ทำการใช้วิธีการประกาศทั้ง 2 แบบคือทั้งแบบ ประกาศ ตัวแปร NSThread ขึ้นมาก่อน แล้วค่อยเรียก Start และอีกแบบก็คือไม่ต้องประกาศ ตัวแปร แต่เรียกใช้ class method ขึ้นมาเลย

ยังมีอีก method ที่น่าสนใจก็คือ sleepForTimeInterval โดยทำหน้าที่คือ หยุดการทำงานตามเวลาที่กำหนด สาเหตุก็เพราะว่า เนื่องจากว่า Thread นั้นทำงานแยกกัน อาจจะมีบาง Thread ที่ทำงานเสร็จก่อน หรือเสร็จหลัง Main Program ก็ได้ ฉนั้นจึงทำการรอให้ แต่ละ Thread ทำงานเสร็จก่อน แล้วค่อยจบโปรแกรม เพื่อที่ว่าป้องกันปัญหา Memory Leak หรือโปรแกรมทำงานผิดพลาด

และหลังจาก compile และ run แล้วผลลัพธ์ที่ได้ จะได้ประมาณแบบนี้

จะเห็นว่า ลำดับ แต่อันจะไม่เรียงกัน อาจจะสลับกันไปมา ก็เนื่องจากว่า Thread แต่ละอันนั้นทำงานแยกจากกัน

*** ข้อระวังสำหรับการใช้ Thread ใน Objective-C ***
ใน Thread ถ้ามีการประกาศตัวแปร หรือว่าใช้งานในลักษณะที่ต้องมีการจอง memory ต้องมี NSAutoreleasePool ด้วยเสมอ

เช่น

– (void) PrintToConsole : NSString* text  ถ้าเราจะเปลี่ยน code การทำงานให้มันพิมพ์ออกที่หน้า console เหมือนกันแต่เราไม่อยากใช้ NSLog ก็อาจจะเขียนใหม่ได้ว่า

การเขียนแบบนี้เวลา run จะเกิด error น่ะครับ เพราะว่า [text UTF8String] มันจะไปจอง memory ใหม่แล้วส่งค่า char* กลับมา ฉนั้น ถ้าไม่มี NSAutoreleasePool มันจะ error

การเขียนที่ถูกต้องควรจะเป็น

สำหรับ tutorial นี้จริงๆผมกะว่าจะเป็น guide ง่ายๆสำหรับคนที่รู้เรื่อง thread อยู่แล้ว ก็ถ้าใครยังไม่เข้าใจ ต้องการรู้เรื่องเกี่ยวกับ thread เพิ่มมากขึ้นก็แนะนำให้ไปอ่าน link ที่ข้างบน แล้วก็ค้นหาจาก google ก็ได้ครับ

ครั้งหน้า ก็ยังอยู่กับ objective-c น่ะครับ ส่วน source สำหรับ วันนี้ก็โหลดได้ที่นี่เลย