System.Timers.Timer เทียบกับ System.Threading.Timer


565

ฉันได้ตรวจสอบตัวจับเวลาที่เป็นไปได้เมื่อเร็ว ๆ นี้System.Threading.TimerและSystem.Timers.Timerเป็นสิ่งที่จำเป็นสำหรับฉัน (เนื่องจากพวกเขาสนับสนุนการรวมเธรด)

ฉันกำลังสร้างเกมและวางแผนที่จะใช้กิจกรรมทุกประเภทโดยมีช่วงเวลาที่แตกต่างกัน ฯลฯ

อันไหนดีที่สุด?

คำตอบ:


363

บทความนี้มีคำอธิบายที่ครอบคลุมพอสมควร:

"การเปรียบเทียบคลาสตัวจับเวลาในไลบรารีคลาสของ. NET Framework " - พร้อมใช้งานเป็นไฟล์. chm

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

ฉันไม่เชื่อว่ามีความแตกต่างระหว่างสองอย่างที่เกี่ยวข้องกับระยะเวลาของคุณเล็ก


69
ฉันคิดว่าข้อความที่ตัดตอนมานี้ enlightening: "ซึ่งแตกต่างจาก System.Windows.Forms.Timer คลาส System.Timers.Timer โดยค่าเริ่มต้นจะเรียกตัวจัดการเหตุการณ์ตัวจับเวลาของคุณบนเธรดคนงานที่ได้รับจากกลุ่มเธรดรันไทม์ภาษาทั่วไป (CLR) . [... ] คลาส System.Timers.Timer ให้วิธีที่ง่ายในการจัดการกับภาวะที่กลืนไม่เข้าคายไม่ออกนี้มันเปิดเผยคุณสมบัติสาธารณะ SynchronizingObject สาธารณะการตั้งค่าคุณสมบัตินี้เป็นอินสแตนซ์ของแบบฟอร์ม Windows (หรือการควบคุมในแบบฟอร์ม Windows) จะ ตรวจสอบให้แน่ใจว่ารหัสในตัวจัดการเหตุการณ์ที่ผ่านไปของคุณทำงานบนเธรดเดียวกันกับที่
mico

7
ตามที่กระทู้ส่วนความปลอดภัยในการThreading.Timer's บทความ MSDNเป็นอย่างดีด้ายปลอดภัย ...
ปีเตอร์

62
System.Threading.Timerเป็น "แดกดัน" ไม่ปลอดภัยเธรดSystem.Threading.Threadและและหัวข้อที่ได้รับผ่านสระว่ายน้ำ เพียงเพราะคลาสเหล่านี้ไม่จับมือคุณและจัดการการใช้lockคำหลักเองไม่ได้หมายความว่าคลาสเหล่านี้ไม่ได้เป็นเธรดที่ปลอดภัย คุณอาจจะบอกว่าSystem.Threading.Threadไม่ใช่ threadsafe เพราะมันเป็นเรื่องจริง
Kirk Woll

8
นอกจากนี้ช่วงเวลา System.Timer.Timer สามารถเป็น Int32 System.Threading ช่วงเวลาของตัวจับเวลาสามารถสูงถึง Int64
Brent

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

169

System.Threading.Timerเป็นตัวจับเวลาธรรมดา มันโทรกลับคุณบนเธรดพูลเธรด (จากพูลของผู้ปฏิบัติงาน)

System.Timers.Timerคือ a System.ComponentModel.Componentที่ตัดคำSystem.Threading.Timerและให้คุณสมบัติเพิ่มเติมบางอย่างที่ใช้สำหรับการส่งข้อความในเธรดเฉพาะ

System.Windows.Forms.Timerแทนที่จะล้อมรอบข้อความดั้งเดิมเท่านั้น HWNDและใช้ตัวจับเวลาหน้าต่างเพื่อเพิ่มเหตุการณ์ในการวนซ้ำข้อความ HWNDs

หากแอปของคุณไม่มี UI และคุณต้องการตัวจับเวลา. Net ที่มีน้ำหนักเบาและใช้งานได้ทั่วไปมากที่สุด (เพราะคุณมีความสุขในการหาเธรด / การแจกจ่ายของคุณเอง) ก็System.Threading.Timerถือว่าดีตามที่ได้รับในกรอบ

ฉันไม่ชัดเจนว่าปัญหา 'ไม่ปลอดภัยเธรด' ที่ควรมีSystem.Threading.Timerคืออะไร บางทีมันก็เหมือนกับที่ถามในคำถามนี้: Thread-safety ของ System.Timers.Timer vs System.Threading.Timerหรือบางทีทุกคนก็หมายความว่า:

  1. มันง่ายที่จะเขียนเงื่อนไขการแข่งขันเมื่อคุณใช้ตัวจับเวลา เช่นดูคำถามนี้: จับเวลา (ระบบ. เธรด) ความปลอดภัยของเธรด

  2. เข้าร่วมการแจ้งเตือนตัวจับเวลาอีกครั้งซึ่งเหตุการณ์ตัวจับเวลาของคุณสามารถเรียกใช้และโทรกลับหาคุณเป็นครั้งที่สองก่อนที่คุณจะประมวลผลเหตุการณ์แรกให้เสร็จสิ้น เช่นดูคำถามนี้: การดำเนินการที่ปลอดภัยสำหรับเธรดโดยใช้ System.Threading.Timer และ Monitor


True System.Timers.Timerใช้System.Threading.Timerภายใน ดูรหัสที่มา
stomy

120

ในหนังสือของเขา " CLR Via C # ", Jeff Ritcherไม่สนับสนุนการใช้System.Timers.Timerตัวจับเวลานี้มาจากการSystem.ComponentModel.Componentอนุญาตให้ใช้ในพื้นผิวการออกแบบของ Visual Studio ดังนั้นมันจะมีประโยชน์ก็ต่อเมื่อคุณต้องการตัวจับเวลาบนพื้นผิวการออกแบบ

เขาชอบที่จะใช้System.Threading.Timerสำหรับงานพื้นหลังในเธรดพูลเธรด


36
มันสามารถใช้ในพื้นผิวการออกแบบ - มันไม่ได้หมายความว่ามันจะต้องเป็นและไม่มีผลกระทบที่เป็นอันตรายจากการไม่ทำเช่นนั้น การอ่านบทความในคำตอบก่อนหน้าสำหรับคำถามนี้ Timers.Timer ดูเหมือนจะดีกว่า Threading.Timer
สตีเฟ่น Drew

6
สิ่งที่เป็นที่นิยมคือขึ้นอยู่กับบริบทใช่มั้ย ตามที่ฉันเข้าใจแล้ว System.Threading.Timer จะเรียกใช้การติดต่อกลับผ่านในเธรดผู้ทำงานใหม่จาก ThreadPool ซึ่งฉันคิดว่าเป็นเหตุผลที่ไม่จำเป็นต้องปลอดภัยต่อเธรด คินดาทำให้รู้สึก ดังนั้นในทางทฤษฎีคุณไม่ต้องกังวลเกี่ยวกับการปั่นด้ายด้ายคนงานของคุณเองเนื่องจากตัวจับเวลานี้จะทำเพื่อคุณ ดูเหมือนว่ามีประโยชน์อย่างน่าขัน
Finster

6
การใช้System.Threading.Timerคล้ายกับการใช้เธรดพูลหรือการสร้างเธรดของคุณเอง ของหลักสูตรชั้นเรียนเหล่านี้ไม่ได้จัดการประสานสำหรับคุณ - ว่างานของคุณ! ไม่ว่าเธรดพูลเธรดเธรดของคุณเองหรือตัวจับเวลาการโทรกลับจะจัดการกับการล็อก - กับวัตถุใดและในแบบใดและในสถานการณ์ใดที่คุณจำเป็นต้องล็อคต้องใช้วิจารณญาณที่ดีและตัวตั้งเวลารุ่นเธรด อาการเป็นเมล็ด
Kirk Woll

2
-1 คำตอบนี้เป็นอัตนัยหรือความเห็นตั้งแต่เริ่มต้นและไม่มีข้อมูลที่เป็นรูปธรรมว่าทำไม System.Threading.Timer เป็นที่ต้องการโดย Jeff Ritcher
Brian Ogden

42

ข้อมูลจาก Microsoft เกี่ยวกับเรื่องนี้ (ดูหมายเหตุใน MSDN ):

  • System.Timers.Timerซึ่ง fires เหตุการณ์และเรียกใช้งานโค้ดในหนึ่งหรือหลายเหตุการณ์ sinks ในช่วงเวลาปกติ คลาสนี้มีจุดประสงค์เพื่อใช้เป็นเซิร์ฟเวอร์หรือส่วนประกอบบริการในสภาพแวดล้อมแบบมัลติเธรด มันไม่มีส่วนต่อประสานกับผู้ใช้และไม่สามารถมองเห็นได้ในขณะใช้งานจริง
  • System.Threading.Timerซึ่งดำเนินการเมธอด callback เดี่ยวบนเธรดพูลเธรดในช่วงเวลาปกติ วิธีการโทรกลับถูกกำหนดเมื่อตัวจับเวลาถูกสร้างอินสแตนซ์และไม่สามารถเปลี่ยนแปลงได้ เช่นคลาส System.Timers.Timer คลาสนี้มีไว้สำหรับใช้เป็นเซิร์ฟเวอร์หรือส่วนประกอบบริการในสภาพแวดล้อมแบบมัลติเธรด มันไม่มีส่วนต่อประสานกับผู้ใช้และไม่สามารถมองเห็นได้ในขณะใช้งานจริง
  • System.Windows.Forms.Timer (. NET Framework เท่านั้น) ซึ่งเป็นองค์ประกอบของ Windows Forms ที่ใช้สร้างเหตุการณ์และเรียกใช้งานโค้ดในเหตุการณ์หนึ่งครั้งขึ้นไปในช่วงเวลาปกติ คอมโพเนนต์ไม่มีส่วนต่อประสานผู้ใช้และออกแบบมาเพื่อใช้ในสภาพแวดล้อมแบบเธรดเดียว มันรันบนเธรด UI
  • System.Web.UI.Timer (. NET Framework เท่านั้น), คอมโพเนนต์ ASP.NET ที่ทำหน้าเว็บแบบอะซิงโครนัสหรือแบบซิงโครนัส postbacks ในช่วงเวลาปกติ

เป็นที่น่าสนใจที่จะกล่าวถึงที่System.Timers.Timerเลิกกับ. NET Core 1.0 แต่ถูกนำมาใช้อีกครั้งใน. NET Core 2.0 (/. NET Standard 2.0) เป้าหมายของ. NET Standard 2.0 ก็คือมันควรจะง่ายที่สุดเท่าที่จะทำได้เพื่อสลับจาก. NET Framework ซึ่งน่าจะเป็นเหตุผลที่มันกลับมา

เมื่อเลิกใช้งานแล้ว. NET Portability Analyzer Visual Studio Add-Inแนะนำให้ใช้System.Threading.Timerแทน

ดูเหมือนว่า Microsoft โปรดปรานSystem.Threading.Timerก่อนหน้าSystem.Timers.Timerนี้

แก้ไขหมายเหตุ 2018-11-15: ฉันต้องการเปลี่ยนคำตอบของฉันเนื่องจากข้อมูลเก่าเกี่ยวกับ. NET Core 1.0 ไม่ถูกต้องอีกต่อไป


2
ดูเหมือนว่าจะเป็นความจริง: github.com/npgsql/npgsql/issues/471#issuecomment-94104090
Marco Sulla

@ Taegost การใช้งานยังมี จำกัด - ดู MSDN msdn.microsoft.com/en-us/library/…และอ่านหมายเหตุเกี่ยวกับความพร้อมใช้งานของแพลตฟอร์ม
astrowalker

@astrowalker - ขอบคุณสำหรับสิ่งนั้นในเวลาที่ฉันแสดงความคิดเห็นคำตอบนี้แทบจะไม่มีรายละเอียดเลย เนื่องจากตอนนี้มีรายละเอียดที่ฉันถามฉันจึงลบความคิดเห็นของฉัน
Taegost

1
System.Timers.Timer ได้รับการสนับสนุนใน. NET Standard 2.0 และ. NET Core 2.0 ขึ้นไป docs.microsoft.com/en-us/dotnet/api/system.timers.timer (เลื่อนไปที่ส่วนท้ายของบทความ)
Lee Grissom

นอกจากนี้ยังมีSystem.Windows.Threading.DispatcherTimerต่อคำตอบนี้
SpeedCoder5

39

ความแตกต่างที่สำคัญอย่างหนึ่งที่ไม่ได้กล่าวถึงข้างต้นซึ่งอาจทำให้คุณไม่สนใจคือการSystem.Timers.Timerกลืนข้อยกเว้นอย่างเงียบ ๆ ในขณะที่System.Threading.Timerไม่มี

ตัวอย่างเช่น:

var timer = new System.Timers.Timer { AutoReset = false };
timer.Elapsed += (sender, args) =>
{
    var z = 0;
    var i = 1 / z;
};
timer.Start();

VS

var timer = new System.Threading.Timer(x =>
{
    var z = 0;
    var i = 1 / z;
}, null, 0, Timeout.Infinite);

1
ฉันเพิ่งเจอปัญหานี้กับ Timers.Timer และมันก็เจ็บปวดมาก ... ความคิดใด ๆ ที่ฉันสามารถเขียนด้วย Threading.Timer ได้? stackoverflow.com/questions/41618324/…
Tez Wingfield

7
ไม่มีการตรวจจับที่ว่างเปล่าในซอร์สโค้ด ดูรหัสที่มาของ System.Timers.Timer ที่นี่
stomy

Omgsh ทำไมโปรแกรมเมอร์ MS ไม่สามารถทำสิ่งเดียวกันเหมือนกันได้จริงหรือ
xmedeko

2
ตัวอย่างไม่ได้อธิบายว่านกนางแอ่นตัวหนึ่งจะมีข้อยกเว้นได้อย่างไรและอีกอันไม่ได้ มีคนช่วยกรุณากรอกรายละเอียด?
ฌอน

24

ฉันพบการเปรียบเทียบสั้น ๆ จากMSDN

. NET Framework Class Library ประกอบด้วยสี่คลาสที่ชื่อว่า Timer ซึ่งแต่ละตัวมีฟังก์ชันการทำงานที่แตกต่างกัน:

System.Timers.Timerซึ่งไฟเหตุการณ์และรันรหัสในหนึ่งหรือมากกว่าหนึ่งเหตุการณ์จมในช่วงเวลาปกติ คลาสมีไว้สำหรับใช้เป็นเซิร์ฟเวอร์หรือส่วนประกอบบริการในสภาพแวดล้อมแบบมัลติเธรด มันไม่มีส่วนต่อประสานกับผู้ใช้และไม่สามารถมองเห็นได้ในขณะใช้งานจริง

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

System.Windows.Forms.Timerเป็นส่วนประกอบของ Windows Forms ที่สร้างเหตุการณ์และเรียกใช้งานโค้ดในหนึ่งเหตุการณ์ขึ้นไปในช่วงเวลาปกติ คอมโพเนนต์ไม่มีส่วนต่อประสานผู้ใช้และออกแบบมาเพื่อใช้ในสภาพแวดล้อมแบบเธรดเดียว

System.Web.UI.Timerคอมโพเนนต์ ASP.NET ที่ดำเนินการหน้าเว็บแบบอะซิงโครนัสหรือแบบซิงโครนัสในช่วงเวลาปกติ


1

สองชั้นเทียบเท่าหน้าที่ยกเว้นว่าSystem.Timers.Timerมีตัวเลือกที่จะเรียกเรียกกลับจับเวลาหมดอายุทั้งหมดผ่านISynchronizeInvokeโดยการตั้งค่าSynchronizingObject มิฉะนั้นตัวจับเวลาทั้งสองจะเรียกการเรียกกลับที่หมดอายุในเธรดพูลเธรด

เมื่อคุณลาก a System.Timers.Timerลงบนพื้นผิวการออกแบบฟอร์ม Windows Visual Studio จะตั้งค่าSynchronizingObjectให้กับวัตถุฟอร์มซึ่งทำให้การโทรกลับหมดอายุทั้งหมดจะถูกเรียกบนเธรด UI


1

จาก MSDN: System.Threading.Timerเป็นตัวจับเวลาแบบเรียบง่ายน้ำหนักเบาที่ใช้วิธีการโทรกลับและให้บริการโดยเธรดพูลเธรด ไม่แนะนำให้ใช้กับ Windows Forms เนื่องจากการโทรกลับไม่เกิดขึ้นในเธรดส่วนต่อประสานผู้ใช้ System.Windows.Forms.Timerเป็นตัวเลือกที่ดีกว่าสำหรับใช้กับ Windows Forms สำหรับฟังก์ชั่นจับเวลาบนเซิร์ฟเวอร์คุณอาจพิจารณาใช้System.Timers.Timerซึ่งจะเพิ่มเหตุการณ์และมีคุณสมบัติเพิ่มเติม

แหล่ง

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