เมื่อใดควรใช้เธรดพูลใน C #? [ปิด]


127

ฉันพยายามเรียนรู้การเขียนโปรแกรมแบบมัลติเธรดใน C # และฉันก็สับสนว่าเมื่อใดควรใช้เธรดพูลกับการสร้างเธรดของฉันเอง หนังสือเล่มหนึ่งแนะนำให้ใช้เธรดพูลสำหรับงานเล็ก ๆ เท่านั้น (ไม่ว่าจะหมายถึงอะไรก็ตาม) แต่ดูเหมือนว่าฉันจะไม่พบแนวทางที่แท้จริง คุณใช้ข้อพิจารณาอะไรบ้างในการตัดสินใจเขียนโปรแกรมนี้

คำตอบ:


47

หากคุณมีงานโลจิคัลจำนวนมากที่ต้องการการประมวลผลคงที่และคุณต้องการให้ทำแบบขนานให้ใช้พูล + ตัวกำหนดตารางเวลา

หากคุณต้องการสร้างงานที่เกี่ยวข้องกับ IO ของคุณไปพร้อม ๆ กันเช่นการดาวน์โหลดข้อมูลจากเซิร์ฟเวอร์ระยะไกลหรือการเข้าถึงดิสก์ แต่ต้องทำเช่นนี้ทุกๆสองสามนาทีจากนั้นสร้างเธรดของคุณเองและฆ่าพวกมันเมื่อคุณทำเสร็จแล้ว

แก้ไข: เกี่ยวกับข้อควรพิจารณาบางประการฉันใช้เธรดพูลสำหรับการเข้าถึงฐานข้อมูลฟิสิกส์ / การจำลอง AI (เกม) และสำหรับงานสคริปต์ที่รันบนเครื่องเสมือนที่ประมวลผลงานที่ผู้ใช้กำหนดจำนวนมาก

โดยปกติพูลประกอบด้วย 2 เธรดต่อโปรเซสเซอร์ (น่าจะเป็น 4 เธรดในปัจจุบัน) อย่างไรก็ตามคุณสามารถตั้งค่าจำนวนเธรดที่คุณต้องการได้หากคุณทราบจำนวนเธรดที่คุณต้องการ

แก้ไข: สาเหตุที่ต้องสร้างเธรดของคุณเองเนื่องจากการเปลี่ยนแปลงบริบท (นั่นคือเมื่อเธรดจำเป็นต้องสลับเข้าและออกจากกระบวนการพร้อมกับหน่วยความจำ) หากมีการเปลี่ยนแปลงบริบทที่ไร้ประโยชน์ให้พูดเมื่อคุณไม่ได้ใช้เธรดของคุณเพียงแค่ปล่อยให้พวกเขานั่งเฉยๆตามที่ใคร ๆ พูดก็สามารถครึ่งหนึ่งของประสิทธิภาพของโปรแกรมของคุณได้อย่างง่ายดาย (เช่นคุณมีเธรดนอน 3 เธรดและเธรดที่ใช้งานอยู่ 2 เธรด) ดังนั้นหากผู้ที่กำลังดาวน์โหลดเธรดกำลังรอพวกเขากำลังจะกิน CPU เป็นจำนวนมากและทำให้แคชสำหรับแอปพลิเคชันจริงของคุณเย็นลง


2
โอเค แต่คุณอธิบายได้ไหมว่าทำไมคุณถึงเข้าหามัน ตัวอย่างเช่นข้อเสียของการใช้เธรดพูลเพื่อดาวน์โหลดจากเซิร์ฟเวอร์ระยะไกลหรือทำดิสก์ IO คืออะไร

8
หากเธรดกำลังรออยู่บนอ็อบเจ็กต์การซิงโครไนซ์ (เหตุการณ์, เซมาฟอร์, mutex ฯลฯ ) เธรดจะไม่ใช้ CPU
Brannon

7
ดังที่ Brannon กล่าวว่าตำนานทั่วไปคือการสร้างเธรดหลายเธรดจะส่งผลต่อประสิทธิภาพ จริงๆแล้วเธรดที่ไม่ได้ใช้ใช้ทรัพยากรน้อยมาก สวิตช์บริบทเริ่มเป็นปัญหาเฉพาะในเซิร์ฟเวอร์ที่มีความต้องการสูงมาก (ในกรณีนี้โปรดดูพอร์ตที่เสร็จสมบูรณ์ของ I / O สำหรับทางเลือกอื่น)
FDCastel

12
เธรดที่ไม่ได้ใช้งานมีผลต่อประสิทธิภาพหรือไม่ ขึ้นอยู่กับว่าพวกเขารออย่างไร หากเขียนได้ดีและรอออบเจ็กต์ซิงโครไนซ์ก็ไม่ควรใช้ทรัพยากร CPU หากรอวนซ้ำที่ตื่นขึ้นมาเป็นระยะเพื่อตรวจสอบผลลัพธ์แสดงว่าสิ้นเปลือง CPU เช่นเคยมีการเข้ารหัสที่ดี
บิล

2
เธรดที่มีการจัดการที่ไม่ได้ใช้งานจะกินหน่วยความจำสำหรับสแต็ก โดยค่าเริ่มต้นคือ 1 MiB ต่อเธรด ดังนั้นจึงเป็นการดีกว่าที่จะให้เธรดทั้งหมดทำงาน
Vadym Stetsiak

48

ฉันขอแนะนำให้คุณใช้เธรดพูลใน C # ด้วยเหตุผลเดียวกับภาษาอื่น ๆ

เมื่อคุณต้องการ จำกัด จำนวนเธรดที่รันหรือไม่ต้องการให้มีค่าใช้จ่ายในการสร้างและทำลายเธรดเหล่านี้ให้ใช้เธรดพูล

โดยงานเล็ก ๆ หนังสือที่คุณอ่านหมายถึงงานที่มีอายุการใช้งานสั้น หากใช้เวลาสิบวินาทีในการสร้างเธรดซึ่งทำงานเพียงหนึ่งวินาทีนั่นคือที่เดียวที่คุณควรใช้พูล (ไม่สนใจตัวเลขจริงของฉันนั่นคืออัตราส่วนที่นับ)

มิฉะนั้นคุณจะใช้เวลาส่วนใหญ่ในการสร้างและทำลายเธรดแทนที่จะทำงานที่ตั้งใจจะทำ


28

นี่คือบทสรุปที่ดีของกลุ่มเธรดใน. Net: http://blogs.msdn.com/pedram/archive/2007/08/05/dedicated-thread-or-a-threadpool-thread.aspx

โพสต์ยังมีบางประเด็นเกี่ยวกับเวลาที่คุณไม่ควรใช้เธรดพูลและเริ่มเธรดของคุณเองแทน


8
-1 สำหรับลิงค์ ฉันแน่ใจว่ามันเป็นลิงค์ที่ดี แต่ฉันคาดหวังว่า SO จะพอเพียง
Jon Davis

26
@ stimpy77 - นั่นเป็นความคาดหวังที่ผิด SO ไม่สามารถพึ่งตัวเองได้เพราะไม่ใช่ทั้งผู้มีอำนาจสูงสุดในทุกคำถามหรือข้อมูลเชิงลึกทั้งหมดในแต่ละหัวข้อสามารถ (และควร) ซ้ำกันในแต่ละคำตอบ SO ที่สัมผัสกับหัวข้อนั้น (และฉันไม่คิดว่าคุณมีชื่อเสียงมากพอที่จะลงคะแนนทุกคำตอบของ Jon Skeet เพียงอย่างเดียวที่มีลิงก์ขาออกนับประสาคำตอบทั้งหมดจากผู้ใช้ SO ทั้งหมดที่มีลิงก์ขาออก :-))
Franci Penov

2
บางทีฉันอาจจะรวบรัดเกินไปบางทีฉันควรชี้แจง ฉันไม่ได้ต่อต้านการเชื่อมโยง ฉันไม่เห็นด้วยกับคำตอบที่มีเพียงลิงค์ ฉันไม่คิดว่านั่นเป็นคำตอบ ตอนนี้หากมีการโพสต์สรุปสั้น ๆ ของคำตอบเพื่อสรุปว่าเนื้อหาที่เชื่อมโยงนำไปใช้อย่างไรนั่นก็เป็นเรื่องที่ยอมรับได้ นอกจากนี้ฉันมาที่นี่เพื่อหาคำตอบสำหรับปัญหาเดียวกันและคำตอบนี้ทำให้ฉันหงุดหงิดเพราะมันเป็นลิงค์อื่นที่ฉันต้องคลิกเพื่อให้มีความคิดเกี่ยวกับสิ่งที่อาจพูดได้โดยอ้างอิงถึงปัญหานั้น ๆ อย่างไรก็ตาม Jon Skeet เกี่ยวข้องกับเรื่องนี้ตรงไหน? แล้วทำไมต้องแคร์?
Jon Davis

8
"คุณเข้ามาที่โพสต์นี้สองปีหลังจากที่โพสต์และสิ่งที่ฉันคัดลอกที่นี่อาจล้าสมัยไปแล้วในตอนนี้" ดังนั้นอาจเชื่อมโยง โพสต์สรุปสั้น ๆ แต่สมบูรณ์เมื่อโพสต์ลิงก์คุณจะไม่มีทางรู้ว่าลิงก์ค้างหรือตาย
Jon Davis

2
ฉันไม่เห็นด้วยกับ stimpy: ไม่ใช่แนวคิดของการโพสต์ที่มีข้อมูลมากมายเนื่องจากไม่มีความสามารถและไม่เรียกใครจากสิ่งนี้ ฉันคิดว่ามีแนวโน้มที่ลิงก์จะใช้งานไม่ได้มากกว่าที่เนื้อหาจะเลิกใช้งาน / ไม่ได้รับผลกระทบ ดังนั้นเนื้อหาเพิ่มเติมจึงดีเมื่อมีโอกาส เราทุกคน (ส่วนใหญ่) เป็นอาสาสมัครดังนั้นจงขอบคุณสำหรับสิ่งที่คุณได้รับ - ขอบคุณ Franci :)
zanlok

14

ขอแนะนำให้อ่าน e-book ฟรีเล่มนี้: Threading in C # โดย Joseph Albahari

อย่างน้อยอ่านส่วน "เริ่มต้นใช้งาน" e-book ให้คำแนะนำที่ยอดเยี่ยมและมีข้อมูลเธรดขั้นสูงมากมายเช่นกัน

รู้หรือไม่ว่าการใช้เธรดพูลเป็นเพียงการเริ่มต้น จากนั้นคุณจะต้องพิจารณาว่าวิธีใดในการเข้าสู่เธรดพูลที่เหมาะสมกับความต้องการของคุณมากที่สุด:

  • ไลบรารีแบบขนานงาน (.NET Framework 4.0)
  • ThreadPool.QueueUserWorkItem
  • ผู้รับมอบสิทธิ์แบบอะซิงโครนัส
  • BackgroundWorker

e-book เล่มนี้อธิบายสิ่งเหล่านี้ทั้งหมดและแนะนำว่าควรใช้เมื่อใดเทียบกับสร้างเธรดของคุณเอง


8

เธรดพูลถูกออกแบบมาเพื่อลดการสลับบริบทระหว่างเธรดของคุณ พิจารณากระบวนการที่มีส่วนประกอบหลายอย่างกำลังทำงานอยู่ แต่ละองค์ประกอบเหล่านั้นสามารถสร้างเธรดของผู้ปฏิบัติงานได้ ยิ่งมีเธรดในกระบวนการของคุณมากเท่าไหร่ก็ยิ่งเสียเวลาในการสลับบริบทมากขึ้นเท่านั้น

ตอนนี้ถ้าแต่ละองค์ประกอบเหล่านั้นจัดคิวไอเท็มไปยังเธรดพูลคุณจะมีค่าโสหุ้ยการสลับบริบทน้อยลงมาก

เธรดพูลได้รับการออกแบบมาเพื่อเพิ่มประสิทธิภาพการทำงานระหว่าง CPU ของคุณ (หรือแกน CPU) นั่นคือเหตุผลที่โดยค่าเริ่มต้นเธรดพูลจะสปินหลายเธรดต่อโปรเซสเซอร์

มีบางสถานการณ์ที่คุณไม่ต้องการใช้เธรดพูล หากคุณกำลังรอ I / O หรือกำลังรอเหตุการณ์ ฯลฯ คุณจะผูกเธรดพูลเธรดนั้นและไม่สามารถใช้โดยผู้อื่นได้ แนวคิดเดียวกันนี้ใช้กับงานที่ต้องรันเป็นเวลานานแม้ว่าสิ่งที่ถือว่าเป็นงานที่ต้องใช้เวลานานจะเป็นเรื่องส่วนตัว

Pax Diablo เป็นจุดที่ดีเช่นกัน การปั่นกระทู้ไม่ฟรี ต้องใช้เวลาและใช้หน่วยความจำเพิ่มเติมสำหรับพื้นที่สแต็ก เธรดพูลจะใช้เธรดซ้ำเพื่อตัดจำหน่ายต้นทุนนี้

หมายเหตุ: คุณถามเกี่ยวกับการใช้เธรดพูลเธรดเพื่อดาวน์โหลดข้อมูลหรือดำเนินการดิสก์ I / O คุณไม่ควรใช้เธรดพูลเธรดสำหรับสิ่งนี้ (ด้วยเหตุผลที่ฉันระบุไว้ข้างต้น) ใช้ I / O แบบอะซิงโครนัสแทน (หรือที่เรียกว่าเมธอด BeginXX และ EndXX) สำหรับFileStreamที่จะเป็นและBeginRead EndReadสำหรับHttpWebRequestที่จะเป็นและBeginGetResponse EndGetResponseมีความซับซ้อนในการใช้งานมากกว่า แต่เป็นวิธีที่เหมาะสมในการดำเนินการ I / O แบบมัลติเธรด


1
ThreadPool เป็นระบบอัตโนมัติที่ชาญฉลาด "หากคิวยังคงอยู่นิ่งนานกว่าครึ่งวินาทีคิวจะตอบสนองโดยการสร้างเธรดเพิ่มขึ้น - หนึ่งทุกครึ่งวินาที - ขึ้นอยู่กับความจุของเธรดพูล" ( albahari.com/threading/#_Optimizing_the_Thread_Pool ) นอกจากนี้การดำเนินการแบบอะซิงโครนัสเกือบกับ BeginXXX-EndXXX ยังใช้ผ่าน ThreadPool ดังนั้นจึงเป็นเรื่องปกติที่จะใช้ ThreadPool เพื่อดาวน์โหลดข้อมูลและมักใช้โดยปริยาย
Artru

6

ระวังเธรดพูล. พิจารณาใช้ส่วนขยายแบบขนาน. NET ซึ่งมีจำนวนมากของนามธรรมเชิงตรรกะมากกว่าการดำเนินการแบบเธรด นอกจากนี้ยังมีตัวกำหนดตารางเวลาใหม่ซึ่งควรได้รับการปรับปรุงใน ThreadPool ดูที่นี่


2
เราค้นพบวิธีนี้ยาก! ASP.Net ใช้ Threadpool ปรากฏขึ้นดังนั้นเราจึงไม่สามารถใช้งานได้ในเชิงรุกอย่างที่เราต้องการ
noocyte

3

เหตุผลหนึ่งที่ต้องใช้เธรดพูลสำหรับงานขนาดเล็กเท่านั้นคือเธรดพูลเธรดมีจำนวน จำกัด หากมีการใช้งานเป็นเวลานานเธรดนั้นจะหยุดการใช้งานโดยรหัสอื่น หากสิ่งนี้เกิดขึ้นหลายครั้งจะสามารถใช้เธรดพูลได้

การใช้เธรดพูลอาจมีเอฟเฟกต์เล็กน้อย - ตัวจับเวลา. NET บางตัวใช้เธรดพูลเธรดและจะไม่เริ่มทำงาน


2

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

ในแอปพลิเคชันที่คุณสร้างเธรดจำนวนมากค่าใช้จ่ายในการสร้างเธรดจะมีมาก การใช้เธรดพูลจะสร้างเธรดหนึ่งครั้งและนำมาใช้ใหม่ดังนั้นจึงหลีกเลี่ยงค่าใช้จ่ายในการสร้างเธรด

ในแอปพลิเคชันที่ฉันใช้งานการเปลี่ยนจากการสร้างเธรดเป็นการใช้เธรดพูลสำหรับเธรดที่มีอายุสั้นช่วยให้แอปพลิเคชันผ่านไปได้อย่างแท้จริง


โปรดชี้แจงว่าคุณหมายถึง "เธรดพูล" หรือ "เธรดพูล" สิ่งเหล่านี้แตกต่างกันมาก (อย่างน้อยก็ใน MS CLR)
bzlm

2

เพื่อให้ได้ประสิทธิภาพสูงสุดพร้อมกับยูนิตที่ดำเนินการพร้อมกันให้เขียนเธรดพูลของคุณเองโดยที่พูลของอ็อบเจ็กต์เธรดถูกสร้างขึ้นเมื่อเริ่มต้นระบบและไปที่การบล็อก (ก่อนหน้านี้ถูกระงับ) รอให้บริบททำงาน (อ็อบเจ็กต์ที่มีอินเทอร์เฟซมาตรฐานที่ดำเนินการโดย รหัสของคุณ)

บทความมากมายเกี่ยวกับ Tasks vs. Threads เทียบกับ. NET ThreadPool ไม่สามารถให้สิ่งที่คุณต้องการในการตัดสินใจเรื่องประสิทธิภาพได้ แต่เมื่อคุณเปรียบเทียบพวกเขา Threads จะชนะและโดยเฉพาะกลุ่มของ Threads มีการกระจายสิ่งที่ดีที่สุดในซีพียูและเริ่มต้นได้เร็วขึ้น

สิ่งที่ควรกล่าวถึงคือความจริงที่ว่าหน่วยประมวลผลหลักของ Windows (รวมถึง Windows 10) เป็นเธรดและค่าใช้จ่ายในการสลับบริบทของระบบปฏิบัติการมักจะไม่สำคัญ พูดง่ายๆว่าฉันไม่สามารถหาหลักฐานที่น่าเชื่อถือของบทความเหล่านี้จำนวนมากไม่ว่าบทความจะอ้างว่ามีประสิทธิภาพสูงขึ้นโดยการบันทึกการสลับบริบทหรือการใช้งาน CPU ที่ดีขึ้น

ตอนนี้เพื่อความสมจริง:

พวกเราส่วนใหญ่ไม่ต้องการให้แอปพลิเคชันของเราถูกกำหนดและพวกเราส่วนใหญ่ไม่มีพื้นหลังที่ยากลำบากด้วยเธรดซึ่งมักมาพร้อมกับการพัฒนาระบบปฏิบัติการ สิ่งที่ฉันเขียนไว้ข้างต้นไม่ใช่สำหรับผู้เริ่มต้น

ดังนั้นสิ่งที่สำคัญที่สุดคือการพูดคุยกันคือสิ่งที่ง่ายต่อการเขียนโปรแกรม

หากคุณสร้างเธรดพูลของคุณเองคุณจะมีงานเขียนเล็กน้อยที่ต้องทำเนื่องจากคุณจะต้องเกี่ยวข้องกับการติดตามสถานะการดำเนินการวิธีจำลองการระงับและดำเนินการต่อและวิธีการยกเลิกการดำเนินการรวมทั้งในแอปพลิเคชัน ปิดตัวลง. คุณอาจต้องกังวลด้วยว่าคุณต้องการขยายสระว่ายน้ำแบบไดนามิกหรือไม่และพูลของคุณจะมีขีดจำกัดความสามารถเท่าใด ฉันสามารถเขียนกรอบดังกล่าวได้ภายในหนึ่งชั่วโมง แต่นั่นเป็นเพราะฉันทำมาหลายครั้งแล้ว

บางทีวิธีที่ง่ายที่สุดในการเขียนหน่วยประมวลผลคือการใช้งาน ความสวยงามของงานคือคุณสามารถสร้างขึ้นมาใหม่และเริ่มใช้งานในบรรทัดในโค้ดของคุณ (แม้ว่าอาจมีการรับประกันข้อควรระวัง) คุณสามารถส่งโทเค็นการยกเลิกเพื่อจัดการเมื่อคุณต้องการยกเลิกงาน นอกจากนี้ยังใช้วิธีการสัญญาในการผูกมัดเหตุการณ์และคุณสามารถส่งคืนค่าบางประเภทได้ ยิ่งไปกว่านั้นด้วยการ async และรอมีตัวเลือกมากขึ้นและรหัสของคุณจะพกพาได้มากขึ้น

โดยพื้นฐานแล้วสิ่งสำคัญคือต้องเข้าใจข้อดีข้อเสียของ Tasks vs. Threads เทียบกับ. NET ThreadPool ถ้าฉันต้องการประสิทธิภาพสูงฉันจะใช้เธรดและฉันชอบใช้พูลของฉันเอง

วิธีง่ายๆในการเปรียบเทียบคือเริ่มต้น 512 เธรด 512 งานและ 512 เธรดพูล คุณจะพบความล่าช้าในการเริ่มต้นด้วยเธรด (ด้วยเหตุนี้ทำไมจึงต้องเขียนเธรดพูล) แต่ 512 เธรดทั้งหมดจะทำงานในไม่กี่วินาทีในขณะที่เธรด Tasks และ. NET ThreadPool ใช้เวลาไม่กี่นาทีในการเริ่มต้นทั้งหมด

ด้านล่างนี้เป็นผลการทดสอบดังกล่าว (i5 quad core พร้อม RAM 16 GB) โดยให้เวลาในการรันทุกๆ 30 วินาที รหัสที่เรียกใช้ดำเนินการกับไฟล์ I / O อย่างง่ายบนไดรฟ์ SSD

ผลการทดสอบ


1
FYI ลืมที่จะพูดถึงว่า Tasks และ. NET Threads เป็นการจำลองการทำงานพร้อมกันภายใน. NET และด้วยการจัดการที่ดำเนินการภายใน. NET ไม่ใช่ระบบปฏิบัติการซึ่งจะมีประสิทธิภาพมากกว่าในการจัดการการดำเนินการพร้อมกัน ฉันใช้ Tasks ในหลาย ๆ สิ่ง แต่ฉันใช้ OS Thread เพื่อประสิทธิภาพการดำเนินการที่หนักหน่วง MS อ้างว่า Tasks และ. NET Threads ดีกว่า แต่โดยทั่วไปแล้วจะมีการปรับสมดุลการทำงานพร้อมกันระหว่างแอป. NET อย่างไรก็ตามแอปเซิร์ฟเวอร์จะทำงานได้ดีที่สุดเพื่อให้ระบบปฏิบัติการจัดการการทำงานพร้อมกัน

ชอบที่จะเห็นการใช้งาน Threadpool ที่คุณกำหนดเอง เขียนได้ดี!
Francis

ฉันไม่เข้าใจผลการทดสอบของคุณ das "Units Ran" หมายถึงอะไร คุณเปรียบเทียบ 34 taks กับ 512 เธรด? คุณช่วยอธิบายเรื่องนี้ได้ไหม
Elmue

หน่วยเป็นเพียงวิธีการในการดำเนินการพร้อมกันในเธรดผู้ปฏิบัติงานงานเธรดหรือ. NET ThreadPool การทดสอบของฉันเปรียบเทียบประสิทธิภาพการเริ่มต้น / รัน การทดสอบแต่ละครั้งมีเวลา 30 วินาทีในการวางไข่ 512 เธรดตั้งแต่เริ่มต้น 512 Tasks เธรดผู้ปฏิบัติงาน 512 เธรดพูลหรือดำเนินการต่อกลุ่มที่เริ่มต้น 512 เธรดที่รอบริบทเพื่อดำเนินการ เธรดผู้ปฏิบัติงาน Tasks และ ThreadPool มีการหมุนช้าดังนั้นเวลา 30 วินาทีจึงไม่เพียงพอที่จะหมุนได้ทั้งหมด อย่างไรก็ตามหากจำนวนเธรดของผู้ปฏิบัติงานขั้นต่ำของ ThreadPool ถูกตั้งค่าเป็น 512 ครั้งแรกทั้งเธรดของผู้ปฏิบัติงาน Tasks และ ThreadPool จะหมุนเร็วถึง 512 เธรดตั้งแต่เริ่มต้น


1

เธรดพูลจะดีมากเมื่อคุณมีงานที่ต้องดำเนินการมากกว่าเธรดที่มีอยู่

คุณสามารถเพิ่มงานทั้งหมดลงในเธรดพูลและระบุจำนวนเธรดสูงสุดที่สามารถรันในช่วงเวลาหนึ่ง

ดูหน้านี้บน MSDN: http://msdn.microsoft.com/en-us/library/3dasc8as(VS.80).aspx


โอเคฉันเดาว่ามันเกี่ยวข้องกับคำถามอื่นของฉัน คุณจะรู้ได้อย่างไรว่าคุณมีเธรดที่พร้อมใช้งานในช่วงเวลาใด

มันยากที่จะบอก คุณจะต้องทำการทดสอบประสิทธิภาพ หลังจากจุดเพิ่มเธรดมากขึ้นจะไม่ทำให้คุณมีความเร็วมากขึ้น ค้นหาว่ามีโปรเซสเซอร์กี่ตัวในเครื่องนั่นจะเป็นจุดเริ่มต้นที่ดี จากนั้นขึ้นไปจากที่นั่นหากความเร็วในการประมวลผลไม่ดีขึ้นอย่าเพิ่มเธรดอีก
ลาโจ

1

ใช้เธรดพูลเสมอถ้าทำได้ทำงานในระดับสูงสุดของนามธรรมที่เป็นไปได้ เธรดพูลซ่อนการสร้างและทำลายเธรดสำหรับคุณนี่เป็นสิ่งที่ดี!


1

เวลาส่วนใหญ่คุณสามารถใช้พูลได้เนื่องจากคุณหลีกเลี่ยงกระบวนการสร้างเธรดที่มีราคาแพง

อย่างไรก็ตามในบางสถานการณ์คุณอาจต้องการสร้างเธรด ตัวอย่างเช่นถ้าคุณไม่ใช่คนเดียวที่ใช้เธรดพูลและเธรดที่คุณสร้างนั้นมีอายุการใช้งานยาวนาน (เพื่อหลีกเลี่ยงการใช้ทรัพยากรที่ใช้ร่วมกัน) หรือตัวอย่างเช่นหากคุณต้องการควบคุมขนาดสแต็กของเธรด


1

อย่าลืมตรวจสอบผู้ปฏิบัติงานเบื้องหลัง

ฉันพบสถานการณ์มากมายมันให้สิ่งที่ฉันต้องการโดยไม่ต้องยกของหนัก

ไชโย


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

0

ฉันมักจะใช้ Threadpool เมื่อใดก็ตามที่ฉันต้องการทำอะไรกับเธรดอื่นและไม่สนใจจริงๆว่ามันจะทำงานหรือจบลงเมื่อใด บางอย่างเช่นการบันทึกหรือแม้กระทั่งการดาวน์โหลดไฟล์ในพื้นหลัง (แม้ว่าจะมีวิธีที่ดีกว่าในการทำ async-style) ฉันใช้ด้ายของตัวเองเมื่อฉันต้องการการควบคุมมากขึ้น สิ่งที่ฉันพบคือการใช้คิว Threadsafe (แฮ็คของคุณเอง) เพื่อจัดเก็บ "command objects" นั้นดีเมื่อฉันมีคำสั่งหลายคำสั่งที่ต้องใช้ใน> 1 เธรด ดังนั้นคุณอาจแยกไฟล์ Xml และวางแต่ละองค์ประกอบไว้ในคิวจากนั้นให้หลายเธรดทำงานเพื่อดำเนินการประมวลผลบางอย่างกับองค์ประกอบเหล่านี้ ฉันเขียนวิธีการต่อคิวใน uni (VB.net!) ที่ฉันแปลงเป็น C # ฉันได้รวมไว้ด้านล่างโดยไม่มีเหตุผลใด ๆ (รหัสนี้อาจมีข้อผิดพลาดบางประการ)

using System.Collections.Generic;
using System.Threading;

namespace ThreadSafeQueue {
    public class ThreadSafeQueue<T> {
        private Queue<T> _queue;

        public ThreadSafeQueue() {
            _queue = new Queue<T>();
        }

        public void EnqueueSafe(T item) {
            lock ( this ) {
                _queue.Enqueue(item);
                if ( _queue.Count >= 1 )
                    Monitor.Pulse(this);
            }
        }

        public T DequeueSafe() {
            lock ( this ) {
                while ( _queue.Count <= 0 )
                    Monitor.Wait(this);

                return this.DeEnqueueUnblock();

            }
        }

        private T DeEnqueueUnblock() {
            return _queue.Dequeue();
        }
    }
}

ปัญหาบางประการเกี่ยวกับแนวทางนี้: - การเรียกไปที่ DequeueSafe () จะรอจนกว่ารายการจะเป็น EnqueuedSafe () ลองใช้หนึ่งใน Monitor.Wait () โอเวอร์โหลดที่ระบุการหมดเวลา - การล็อกสิ่งนี้ไม่ได้เป็นไปตามแนวทางปฏิบัติที่ดีที่สุด แต่ให้สร้างฟิลด์อ็อบเจ็กต์แบบอ่านอย่างเดียว - แม้ว่า Monitor.Pulse () จะมีน้ำหนักเบา แต่การเรียกใช้เมื่อคิวมีเพียง 1 รายการจะมีประสิทธิภาพมากกว่า - DeEnqueueUnblock () ควรตรวจสอบคิวนับ> 0 (จำเป็นถ้าใช้ Monitor.PulseAll หรือ wait timeouts)
Craig Nicholson

0

ฉันต้องการเธรดพูลเพื่อกระจายงานข้ามคอร์โดยมีเวลาแฝงน้อยที่สุดเท่าที่จะทำได้และไม่จำเป็นต้องเล่นกับแอปพลิเคชันอื่น ๆ ได้ดี ฉันพบว่าประสิทธิภาพของพูลเธรด. NET ไม่ดีเท่าที่ควร ฉันรู้ว่าฉันต้องการหนึ่งเธรดต่อคอร์ดังนั้นฉันจึงเขียนคลาสแทนพูลเธรดของฉันเอง รหัสที่มีให้เป็นคำตอบอีกคำถาม StackOverflow มากกว่าที่นี่

สำหรับคำถามเดิมเธรดพูลมีประโยชน์สำหรับการแบ่งการคำนวณซ้ำ ๆ ออกเป็นส่วน ๆ ที่สามารถดำเนินการควบคู่กันได้ (สมมติว่าสามารถดำเนินการควบคู่กันได้โดยไม่ต้องเปลี่ยนผลลัพธ์) การจัดการเธรดด้วยตนเองมีประโยชน์สำหรับงานเช่น UI และ IO

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.