如何在特定时间间隔后运行方法
本文关键字:运行 方法 定时间 | 更新日期: 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
的任何调度程序对象上调用它。为了安全起见,我喜欢使用处理我正在更新的控件的调度程序来调用它。