如何在特定时间间隔后运行方法

本文关键字:运行 方法 定时间 | 更新日期: 2023-09-27 18:09:53

很明显:例如,想象我的表单中有一个按钮。当用户点击按钮时,一些void方法应该在30秒后运行。

将有一个void方法DoAfterDelay,它接受两个输入参数。第一个是要执行的方法(使用委托),另一个是时间间隔。写入:

public delegate void IVoidDelegate();
static void DoAfterDelay(IVoidDelegate TheMethod, TimeSpan Interval)
    {
        // *** Some code that will pause the process for "Interval".
        TheMethod();
    }

因此,我只需要一段代码来将进程暂停一段特定的时间间隔。到目前为止,我使用以下代码来完成:

System.Threading.Thread.Sleep(Interval);

但是这段代码对我来说不好,因为它停止了整个进程并冻结了程序。我不想让程序卡在DoAfterDelay方法中。这就是为什么Thread.Sleep是无用的。

有谁能提出更好的方法吗?当然,我已经搜索过了,但我发现的大多数解决方案都是基于使用计时器(比如这里)。但是使用计时器是我最后的意见,因为方法应该运行一次,而使用计时器会使程序难以阅读。所以我在寻找更好的解决方案。或者我需要使用计时器?

我想我必须玩线程,但不确定。所以我想知道有没有人能给我一个解决办法。

如何在特定时间间隔后运行方法

你会使用任务吗?

Task.Factory.StartNew(() =>
{
    System.Threading.Thread.Sleep(Interval);
    TheMethod();
});

这里可以使用。net 4.5的async await功能

您可以使用Task。延迟,以毫秒为单位给出延迟。这是一种非常干净的方式。例:

private async void button1_Click(object sender, EventArgs e)
{
    await Task.Delay(5000);
    TheMethod();
}

有几种创建线程的方法,但当然,这取决于您正在做什么。您可以像这样动态地创建一个线程:

Thread aNewThread = new Thread(
    () => OnGoingFunction()
);
aNewThread.Start();

这个线程将在后台运行。您想要执行的函数应该有一个sleep方法,以便在完成处理后休眠。像这样:

private void OnGoingFunction()
{
   //Code....
   Thread.Sleep(100); //100 ms, this is in the thead so it will not stop your winForm
   //More code....
}

我希望这对你有帮助。

另一个选项是在需要处理线程时创建线程,而不用担心睡眠选项。只需每次创建一个新线程来加载进程

您应该创建一个Coroutine

public IEnumerator waitAndRun()
{
    // WAIT FOR 3 SEC
    yield return new WaitForSeconds(3);
    // RUN YOUR CODE HERE ...
}

并使用:

StartCoroutine(waitAndRun());

DoAfterDelay启动一个计时器,只运行一次,当它过期时,它调用你的void 'TheMethod'函数。为什么会很乱呢?

可以使用

指定确切的秒数
DateTime runTime = new DateTime();
double waitSeconds = (runTime - DateTime.Now).TotalSeconds;
Task.Factory.StartNew(() =>
{
    Thread.Sleep(TimeSpan.FromSeconds(waitSeconds));
    YourMethod();
});

runTime =>当你想要执行方法时

这是你想要的:

public static void Example1c()
{
    Action action = DoSomethingCool;
    TimeSpan span = new TimeSpan(0, 0, 0, 5);
    ThreadStart start = delegate { RunAfterTimespan(action, span); };
    Thread t4 = new Thread(start);
    t4.Start();
    MessageBox.Show("Thread has been launched");
}
public static void RunAfterTimespan(Action action, TimeSpan span)
{
    Thread.Sleep(span);
    action();
}
private static void DoSomethingCool()
{
    MessageBox.Show("I'm doing something cool");
}

使用Action的好处之一是可以很容易地修改它来传递参数。假设你想要传递一个整数给DoSomethingCool。只需这样修改:

public static void Example1c()
{
    Action<int> action = DoSomethingCool;
    TimeSpan span = new TimeSpan(0, 0, 0, 5);
    int number = 10;
    ThreadStart start = delegate { RunAfterTimespan(action, span, number); };
    Thread t4 = new Thread(start);
    t4.Start();
    MessageBox.Show("Thread has been launched");
}
public static void RunAfterTimespan(Action<int> action, TimeSpan span, int number)
{
    Thread.Sleep(span);
    action(number);
}
private static void DoSomethingCool(int number)
{
    MessageBox.Show("I'm doing something cool");
}

非常灵活的…

这是一个简单的针对Dispatcher的扩展,您可以以非阻塞的方式使用。

public static void InvokeAfter(this Dispatcher dispatcher, int milliseconds, Action delayedAction) {
    Task.Factory.StartNew(() => {
        System.Threading.Thread.Sleep(milliseconds);
        dispatcher.Invoke(delayedAction);
    });
}

下面是Lambda的用法:

SomeLabel.Dispatcher.InvokeAfter(3000, () => {
    SomeLabel.Text = "Hello World";
});

您也可以将它用于任何匹配Action的内容。下面是一个使用本地函数的例子…

void doLater(){
    SomeLabel.Text = "Hello World";
}
// Pass the action itself, not the result of the action (i.e. don't use parentheses with 'doLater'.)
SomeLabel.Dispatcher.InvokeAfter(3000, doLater);

注意:您可以在通常调用Invoke的任何调度程序对象上调用它。为了安全起见,我喜欢使用处理我正在更新的控件的调度程序来调用它。