ฉันจะทำให้โปรแกรม C # ของฉันเข้าสู่โหมด 50 มิลลิวินาทีได้อย่างไร


272

ฉันจะทำให้โปรแกรม C # ของฉันเข้าสู่โหมดสลีปเป็นเวลา 50 มิลลิวินาทีได้อย่างไร

นี่อาจเป็นคำถามง่าย ๆ แต่ฉันมีช่วงเวลาที่สมองล้มเหลวชั่วคราว!


1
ติดแท็กใหม่เพื่อ VB.NET ตามคำตอบที่ใช้งานได้เช่นกัน
DrFloyd5

ไม่มี DrFloyd5,; ไม่ทำงานบน VB.NET ใช่มั้ย
Zanoni

16
ถ้าฉันอยู่ในทีม VB.Net ฉันจะเพิ่ม; เป็นความคิดเห็นของตัวละครไปยังรุ่นต่อไปของภาษา ...
โจเอล Coehoorn

4
ฉันคิดว่าโปรแกรมเมอร์ VB นั้นฉลาดพอที่จะเข้าใจสิ่งที่เท่าเทียมกัน
BlueRaja - Danny Pflughoeft

ดีเพื่อให้แน่ใจว่าตอนนี้พวกเขาไม่จำเป็นต้อง
PsychoData

คำตอบ:


330
System.Threading.Thread.Sleep(50);

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

เพียงแค่ลบ;เพื่อให้มันทำงานได้กับ VB.net เช่นกัน


หลังจากเรียกใช้โหมดสลีปแล้วโปรแกรมจะทำงานต่อในพื้นหลัง (โดยไม่ต้องสร้างเธรดใหม่) หรือไม่ นอกจากนี้ถ้าฉันเรียก sleep ในเธรดใหม่เธรดหลักจะทำงานต่อหรือไม่
Jay Nirgudkar

@JayNirgudkar เธรดที่เรียก Sleep จะหยุดทำงาน หัวข้ออื่น ๆ จะไม่ได้รับผลกระทบ
Isak Savo

สิ่งนี้ไม่รับประกันว่าจะถูกต้อง
Akumaburn

150

โดยทั่วไปมี 3 ตัวเลือกสำหรับการรอ (เกือบ) ภาษาการเขียนโปรแกรมใด ๆ :

  1. รอหลวม
    • การดำเนินการบล็อกเธรดสำหรับเวลาที่กำหนด (= ไม่ใช้กำลังการประมวลผล)
    • ไม่สามารถดำเนินการกับเธรดที่ถูกบล็อก / รอได้
    • ไม่ค่อยแม่นยำ
  2. การรอแน่น (หรือที่เรียกว่าการวนซ้ำแน่น)
    • หน่วยประมวลผลไม่ว่างมากสำหรับช่วงเวลารอคอยทั้งหมด (อันที่จริงแล้วโดยปกติจะใช้เวลาประมวลผล 100% ของหนึ่งคอร์)
    • การกระทำบางอย่างสามารถทำได้ในขณะที่รอ
    • แม่นยำมาก
  3. การรวมกันของก่อนหน้า 2
    • มันมักจะรวมประสิทธิภาพการประมวลผลของ 1 และความสามารถ + ความสามารถในการทำสิ่งที่ 2

สำหรับ 1. - การรอหลวมใน C #:

Thread.Sleep(numberOfMilliseconds);

อย่างไรก็ตามตัวกำหนดเวลาการเธรดของ windows ทำให้Sleep()การรับรู้ข้อความอยู่ที่ประมาณ 15ms (ดังนั้น Sleep สามารถรอ 20ms ได้อย่างง่ายดายแม้ว่าจะถูกกำหนดให้รอเพียง 1ms)

สำหรับ 2 - การรออย่างแน่นหนาใน C # คือ:

Stopwatch stopwatch = Stopwatch.StartNew();
while (true)
{
    //some other processing to do possible
    if (stopwatch.ElapsedMilliseconds >= millisecondsToWait)
    {
        break;
    }
}

เรายังสามารถใช้DateTime.Nowหรือวิธีการอื่นในการวัดเวลา แต่Stopwatchเร็วกว่ามาก (และนี่จะทำให้มองเห็นได้ในวงแคบ)

สำหรับ 3 - การรวมกัน:

Stopwatch stopwatch = Stopwatch.StartNew();
while (true)
{
    //some other processing to do STILL POSSIBLE
    if (stopwatch.ElapsedMilliseconds >= millisecondsToWait)
    {
        break;
    }
    Thread.Sleep(1); //so processor can rest for a while
}

รหัสนี้จะบล็อกเธรดเป็นระยะเวลา 1ms (หรือมากกว่านั้นขึ้นอยู่กับการจัดตารางเธรดของระบบปฏิบัติการ) ดังนั้นโปรเซสเซอร์ไม่ว่างสำหรับช่วงเวลาของการบล็อกและรหัสไม่ใช้พลังงาน 100% ของโปรเซสเซอร์ การประมวลผลอื่น ๆ ยังสามารถทำได้ในระหว่างการปิดกั้น (เช่นการอัปเดต UI การจัดการเหตุการณ์หรือการโต้ตอบ / การสื่อสาร)


1
ตัวจับเวลาอาจเป็นที่สนใจด้วย
JonnyRaa

55

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


44

ตั้งแต่ตอนนี้คุณมีคุณสมบัติ async / await วิธีที่ดีที่สุดในการนอนหลับ 50ms คือการใช้งาน TaskDelay:

async void foo()
{
    // something
    await Task.Delay(50);
}

หรือหากคุณกำหนดเป้าหมายเป็น. NET 4 (ด้วย Async CTP 3 สำหรับ VS2010 หรือ Microsoft.Bcl.Async) คุณต้องใช้:

async void foo()
{
    // something
    await TaskEx.Delay(50);
}

วิธีนี้คุณจะไม่บล็อกเธรด UI


คุณสามารถตอบสนองล้างข้อมูลในช่วงเวลาที่ล่าช้านี้ได้หรือไม่ถ้าอยู่ในลูป
Teoman shipahi

ไม่คุณไม่สามารถ. ฉันเชื่อว่ามีFlushAsyncรุ่น
Toni Petrina

6
ทางเลือกที่ไม่ต้องมีการasyncประกาศคือการโทรTask.Delay(50).Wait();
stuartd


14
Thread.Sleep(50);

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

วิธีนี้ไม่ได้ทำการปั๊มมาตรฐาน COM และ SendMessage หากคุณต้องการนอนบนเธรดที่มี STAThreadAttribute แต่คุณต้องการทำการปั๊มมาตรฐาน COM และ SendMessage ให้ลองใช้หนึ่งในโอเวอร์โหลดของวิธีการเข้าร่วมที่ระบุช่วงหมดเวลา

Thread.Join


0

เริ่มต้นด้วย. NET Framework 4.5 คุณสามารถใช้:

using System.Threading.Tasks;

Task.Delay(50).Wait();   // wait 50ms

-1

ดีที่สุดของทั้งสองโลก:

using System.Runtime.InteropServices;

    [DllImport("winmm.dll", EntryPoint = "timeBeginPeriod", SetLastError = true)]
    private static extern uint TimeBeginPeriod(uint uMilliseconds);

    [DllImport("winmm.dll", EntryPoint = "timeEndPeriod", SetLastError = true)]
    private static extern uint TimeEndPeriod(uint uMilliseconds);
    /**
     * Extremely accurate sleep is needed here to maintain performance so system resolution time is increased
     */
    private void accurateSleep(int milliseconds)
    {
        //Increase timer resolution from 20 miliseconds to 1 milisecond
        TimeBeginPeriod(1);
        Stopwatch stopwatch = new Stopwatch();//Makes use of QueryPerformanceCounter WIN32 API
        stopwatch.Start();

        while (stopwatch.ElapsedMilliseconds < milliseconds)
        {
            //So we don't burn cpu cycles
            if ((milliseconds - stopwatch.ElapsedMilliseconds) > 20)
            {
                Thread.Sleep(5);
            }
            else
            {
                Thread.Sleep(1);
            }
        }

        stopwatch.Stop();
        //Set it back to normal.
        TimeEndPeriod(1);
    }
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.