C# 暂停方法以设置毫秒数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1068205/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 07:27:36  来源:igfitidea点击:

Pausing a method for set # of milliseconds

c#multithreadingtimeout

提问by Maxim Zaslavsky

I need to do a sort of "timeout" or pause in my method for 10 seconds (10000 milliseconds), but I'm not sure if the following would work as i do not have multi-threading.

我需要在我的方法中执行某种“超时”或暂停 10 秒(10000 毫秒),但我不确定以下是否有效,因为我没有多线程。

Thread.Sleep(10000);

I will try to use that current code, but I would appreciate if someone could explain the best and correct way of doing this, especially if the above code does not work properly. Thanks!

我将尝试使用该当前代码,但如果有人能解释这样做的最佳和正确方法,我将不胜感激,特别是如果上述代码无法正常工作。谢谢!

UPDATE: This program is actually a console application that in the function in question is doing many HTTPWebRequests to one server, so I wish to delay them for a specified amount of milliseconds. Thus, no callback is required - all that is needed is an "unconditional pause" - basically just the whole thing stops for 10 seconds and then keeps going. I'm pleased that C# still considers this as a thread, so Thread.Sleep(...) would work. Thanks everybody!

更新:这个程序实际上是一个控制台应用程序,在该函数中,它正在对一个服务器执行许多 HTTPWebRequests,所以我希望将它们延迟指定的毫秒数。因此,不需要回调——所需要的只是“无条件暂停”——基本上只是整个事情停止 10 秒钟,然后继续进行。我很高兴 C# 仍然认为这是一个线程,所以 Thread.Sleep(...) 可以工作。谢谢大家!

采纳答案by Jon Skeet

You may not have multi-threading, but you're still executing within a thread: all code executes in a thread.

你可能没有线程,但你仍然在一个线程中执行:所有代码都在一个线程中执行。

Calling Thread.Sleepwill indeed pause the current thread. Do you really want it to unconditionally pause for 10 seconds, or do you want to be able to be "woken up" by something else happening? If you're only actually using one thread, calling Sleepmay well be the best way forward, but it will depend on the situation.

调用Thread.Sleep确实会暂停当前线程。您真的希望它无条件地暂停 10 秒钟,还是希望能够被其他正在发生的事情“唤醒”?如果您实际上只使用一个线程,那么调用很Sleep可能是最好的方法,但这取决于具体情况。

In particular, if you're writing a GUI app you don'twant to use Thread.Sleepfrom the UI thread, as otherwise your whole app will become unresponsive for 10 seconds.

特别是,如果你写你的GUI应用程序希望使用Thread.Sleep从UI线程,否则你的整个应用程序将变得没有反应,持续10秒。

If you could give more information about your application, that would help us to advise you better.

如果你能提供更多关于你的申请的信息,那将有助于我们更好地为你提供建议。

回答by Guffa

Yes, that works just fine.

是的,这很好用。

You don't have to have multiple threads to make use of some of the methods in the Thread class. You always have at least one thread.

您不必有多个线程来使用 Thread 类中的某些方法。你总是至少有一个线程。

回答by Marc Gravell

That will indeed pause the executing thread/method for 10 seconds. Are you seeing a specific problem?

这确实会暂停正在执行的线程/方法 10 秒。你看到一个具体的问题吗?

Note that you shouldn't Sleepthe UI thread - it would be better to do a callback instead.

请注意,您不应该Sleep使用 UI 线程 - 最好进行回调。

Note also that there are other ways of blocking a thread that allow simpler access to get it going again (if you find it is OK after 2s); such as Monitor.Wait(obj, 10000)(allowing another thread to Pulseif needed to wake it up):

另请注意,还有其他阻塞线程的方法,这些方法允许更简单的访问以使其再次运行(如果您在 2 秒后发现它没问题);例如Monitor.Wait(obj, 10000)Pulse如果需要,允许另一个线程唤醒它):

static void Main() {
    object lockObj = new object();
    lock (lockObj) {
        new Thread(GetInput).Start(lockObj);
        Monitor.Wait(lockObj, 10000);
    }
    Console.WriteLine("Main exiting");
}
static void GetInput(object state) {
    Console.WriteLine("press return...");
    string s = Console.ReadLine();
    lock (state) {
        Monitor.Pulse(state);
    }
    Console.WriteLine("GetInput exiting");
}

You can do this with Thread.Interrupttoo, but IMO that is messier.

你也可以这样做Thread.Interrupt,但 IMO 更麻烦。

回答by Ricardo

For a timeout, you should have a static volatile boolean isRunning class field. When the new thread starts, the isRunning must become true, and at the end must become false.

对于超时,您应该有一个 static volatile boolean isRunning 类字段。当新线程开始时,isRunning 必须为真,最后必须为假。

The main thread should have a method that loops for the isRunning during the timeout you define. When the timeout ends, you should implement the logic. But, never use the abort thread method.

主线程应该有一个在您定义的超时期间为 isRunning 循环的方法。当超时结束时,您应该实现逻辑。但是,永远不要使用中止线程方法。

A pause... there isn't a straightforward solution. It depends on what you are doing inside the thread. However, you could look at Monitor.Wait.

停顿一下……没有一个简单的解决方案。这取决于你在线程内做什么。但是,您可以查看Monitor.Wait

回答by Michael Stum

Thread.Sleep is fine, and AFAIK the proper way. Even if you are not Multithreaded: There is always at least one Thread, and if you send that to sleep, it sleeps.

Thread.Sleep 很好,AFAIK 是正确的方法。即使你不是多线程:总是至少有一个线程,如果你将它发送到睡眠状态,它就会睡眠。

Another (bad) way is a spinlock, something like:

另一种()方式是 spinlock,例如:

// Do never ever use this
private void DoNothing(){ }

private void KillCPU()
{
    DateTime target = DateTime.Now.AddSeconds(10);
    while(DateTime.Now < target) DoNothing();
    DoStuffAfterWaiting10Seconds();
}

This is sadly still being used by people and while it will halt your program for 10 seconds, it will run at 100% CPU Utilization (Well, on Multi-Core systems it's one core).

遗憾的是,人们仍在使用它,虽然它会暂停您的程序 10 秒钟,但它会以 100% 的 CPU 利用率运行(嗯,在多核系统上,它是一个核心)。

回答by Groo

You could use a separate thread to do it:

您可以使用单独的线程来执行此操作:

   ThreadPool.QueueUserWorkItem(
       delegate(object state)
       {
           Thread.Sleep(1000);
           Console.WriteLine("done");
       });

But, if this is a Windows Forms app, you will need to invoke the code after the delay from the Gui thread(this article, for example: How to update the GUI from another thread in C#?).

但是,如果这是一个 Windows 窗体应用程序,您将需要在延迟后从 Gui 线程调用代码(这篇文章,例如:如何从 C# 中的另一个线程更新 GUI?)。

[Edit]Just saw your update. If it's a console app, then this will work. But if you haven't used multiple threads so far, then you need to be aware that this code will be executed in a different thread, which means you will have to take care about thread synchronization issues.

[编辑]刚看到你的更新。如果它是一个控制台应用程序,那么这将起作用。但是如果到目前为止你还没有使用过多线程,那么你需要知道这段代码将在不同的线程中执行,这意味着你必须注意线程同步问题。

If you don't need background workers, stick to "keeping it simple".

如果您不需要后台工作人员,请坚持“保持简单”。

回答by MarzSocks

Here is a pause class that will pause for the desired milliseconds and wont consume your CPU resources.

这是一个暂停类,它将暂停所需的毫秒数,并且不会消耗您的 CPU 资源。

public class PauseClass
{
    //(C) Michael Roberg
    //Please feel free to distribute this class but include my credentials.

    System.Timers.Timer pauseTimer = null;

    public void BreakPause()
    {
        if (pauseTimer != null)
        {
            pauseTimer.Stop();
            pauseTimer.Enabled = false;
        }    
    }

    public bool Pause(int miliseconds)
    {
        ThreadPriority CurrentPriority = Thread.CurrentThread.Priority;

        if (miliseconds > 0)
        {
            Thread.CurrentThread.Priority = ThreadPriority.Lowest;

            pauseTimer = new System.Timers.Timer();
            pauseTimer.Elapsed += new ElapsedEventHandler(pauseTimer_Elapsed);

            pauseTimer.Interval = miliseconds;
            pauseTimer.Enabled = true;

            while (pauseTimer.Enabled)
            {
                Thread.Sleep(10);
                Application.DoEvents();
                //pausThread.Sleep(1);
            }

            pauseTimer.Elapsed -= new ElapsedEventHandler(pauseTimer_Elapsed);
        }

        Thread.CurrentThread.Priority = CurrentPriority;

        return true;
    }

    private void pauseTimer_Elapsed(object sender, ElapsedEventArgs e)
    {
        pauseTimer.Enabled = false;
    }
}

回答by Hasala Senevirathne

If you can have an async method, you can do something like to pause the function at a certain location. Once pause is set false it will continue executing the rest of the code in the method. Since this is an async method and delay is async too UI execution wouldn't be affected. * Please note that asyn is supported only in .net 4.5 and higher.

如果你可以有一个异步方法,你可以做一些事情,比如在某个位置暂停函数。一旦 pause 设置为 false,它将继续执行方法中的其余代码。由于这是一个异步方法并且延迟也是异步的,因此 UI 执行不会受到影响。* 请注意,仅 .net 4.5 及更高版本支持 asyn。

bool pause = true;

       void async foo()
        {
        //some code

            while (pause)
             {
             await Task.Delay(100);
             }

        //some code
        }