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 สำหรับ วันนี้ก็โหลดได้ที่นี่เลย

6 thoughts on “Ojective-C Programming – Thread”

  1. ต้องคิดอย่างนี้ครับว่า thread มันเป็นเหมือนโปรแกรมหนึ่งที่ทำงานด้วยตัวมันเอง ฉะนั้นการจะทำให้มันหยุดได้ก็เหมือนกับการคิดว่าจะทำอย่างไรให้โปรแกรมหยุดทำงานนั่นเหละครับ มันไม่มีคำสั่งตายตัวครับ

    แต่หลักการคร่าวๆคือ เราควรจะมีตัวแปรสักตัวที่ main thread และ thread ที่งานอยู่สามารถใช้ร่วมกันได้ เช่นสมมติว่าชื่อ isRun หลังจากนั้นใน thread ย่อยก็ทำการตรวจสอบว่าค่าตัวแปรนี้เป็นจริงหรือไม่ ถ้าใช่ก็ให้ทำงานต่อ

    //main thread
    isRun = true

    // thread 1
    while ( isRun == true )
    {
    }
    อะไรประมาณนี้

  2. ผมอยากทราบว่า ถ้าเราใช้ thread ทำงานใน function ที่มีการวนลูปและใช้เวลาในการวนค่อนข้างนาน ผมอยากจะสร้างปุ่มสำหรับหยุกการทำงานของ thread นั่นชั่วคราว(pause) หรือหยุดการทำงารแบบถาวร(stop) เหมือนกับการเล่นเพลงๆหนึ่งแล้วมีการหยุดชั่วคราวกับเล่นต่ออ่ะครับ ผมต้องทำอย่างไรดีครับ?

  3. จริงๆแล้ว selector มันคือ pointer to function นะครับ ดูตัวอย่าง code ต่อไปนี้

    @interface Student : NSObject {}
    -(void) setName:(NSString*)name;
    @end

    สมมติว่าเราต้องการให้ ใส่ชื่อนักเรียน ถ้าหากเขียน แบบปกติก็จะได้ว่า
    [student setName::@”Ter”];

    ถ้าหากเขียนแบบใช้ selector ก็จะได้ว่า
    [student performSelector:@selector(setName:) withObject:@”Ter”];

    ————————

    ฉนั้นแล้วคำถามว่า มันคล้ายๆกับการแตก thread หรือเปล่า สรุปง่ายๆคือไม่ใช่การสร้าง แต่เป็นการบอกให้ thread ที่จะสร้างรู้ว่าจะไปทำงาน function ไหน )

    [NSThread detachNewThreadSelector:@selector(PrintToConsole: )
    toTarget:sampleConsole
    withObject:@”Hello”];

    จาก code ข้างบนเราสร้าง thread ขึ้นมาแล้วหลังจากนั้นเราก็ใช้ pointer ( selector ) ไปยัง function ที่ชื่อ PrintToConsole: โดยส่ง “Hello” ให้กับ thread เอาไปใช้ในฟังชั่น PrintToConsole ไงครับ

  4. งง มานานนมากก
    กับ @selector Method ช่วย เคลียให้ผมที
    ว่ามันเป็นยังไง ใช้ยังไง
    ผมลองใช้แล้ว ได้บ้าง ไม่ได้บ้าง

    มันคล้่ายๆแตก thread ไปทำปะครับ
    แต่ก็งงๆกับการส่ง parameter ไปให้กับตัว @selector อยู่ครับ

  5. ขอบคุณครับ เล็งๆไว้ว่าจะสั่ง Amazon นะครับ
    เก็บไว้เป็น Reference ครับ ตอนนี้พยายามตระเวณเอา
    กับฝาหรั่งใน Web พยายามดูดๆๆ ดูดซับอะครับ อยากให้
    คนไทยเป็นแบบฝรั่งนะครับ คือความรู้ก็ Share กานนะครับ
    เอาแบบสนุกๆ ใจรักครับ เงินตามมาเองเนอะ

  6. ช่วยแนะนำหนังสือเกี่ยวกับ Objective-C แบบ Intermediate and Advance ดีให้หน่อยครับ อยากได้ครับ

Leave a Reply