我正在开发一个 C# Windows 窗体应用程序,我需要该方法暂停 30 秒,直到它继续执行下一行代码。我已经尝试过
Thread.Sleep()
,它不适合这个应用程序,我知道我应该使用某种计时器来代替。我搜索了很多,但不知道如何实现计时器。
我的代码如下,任何人都可以告诉我应该如何实现计时器。我已经对我希望该方法暂停的位置发表了评论。
private void start_Vid_Click(object sender, EventArgs e)
{
if (video.State != StateFlags.Running)
{
viewport.Visible = true;
video.Play();
}
//Here I want to wait 30 seconds until the next line of code is triggered
viewport.Visible = false;
viewport2.Visible = true;
pictureBox1.Visible = true;
start_Webc();
video2.Play();
}
如果您的应用程序是.Net 4.5应用程序,那么使用起来会更容易一些
Task
:
private async void start_Vid_Click(object sender, EventArgs e)
{
if (video.State != StateFlags.Running)
{
viewport.Visible = true;
video.Play();
}
await Task.Delay(TimeSpan.FromSeconds(30));
viewport.Visible = false;
viewport2.Visible = true;
pictureBox1.Visible = true;
start_Webc();
video2.Play();
}
Task.Delay 在 .NET 4.0 上不可用,但您可以启动任务,该任务只会休眠 30 秒,稍后您可以再次在 UI 线程上继续:
Task.Factory.StartNew(() => Thread.Sleep(30 * 1000))
.ContinueWith((t) =>
{
viewport.Visible = false;
viewport2.Visible = true;
pictureBox1.Visible = true;
start_Webc();
video2.Play();
}, TaskScheduler.FromCurrentSynchronizationContext());
在类级别定义
Timer
的实例(有一些这样的类 - 对于 winforms 应用程序,您应该使用 System.Windows.Forms.Timer
)
static System.Windows.Forms.Timer myTimer = new System.Windows.Forms.Timer();
然后在您的方法中添加行来处理其刻度并启动它:
private void start_Vid_Click(object sender, EventArgs e)
{
if (video.State != StateFlags.Running)
{
viewport.Visible = true;
video.Play();
}
myTimer.Tick += (o,ea) => {
viewport.Visible = false;
viewport2.Visible = true;
pictureBox1.Visible = true;
start_Webc();
video2.Play();
myTimer.Stop();
}
myTimer.Interval = 5000; // 5 seconds
myTimer.Start();
}
System.Threading.Tasks.Task.Delay( 60 * 1000 ).ContinueWith( (_) => StartVoid() );
我们可以使用
中的任务来做到这一点System.Threading.Tasks.Task.Factory.StartNew(() =>
{
Thread.Sleep(5000);
this.Invoke(new Action(() =>
Method1()));
});
还有一种反应式扩展的方法:
Observable.Return("Delayed").Delay(TimeSpan.FromSeconds(30)).Subscribe(val => Console.WriteLine("Executing delayed"));
WPF案例..
public static partial class WpfUtils
{
public static void RunAfter(double seconds, Action action)
{
if (Application.Current.Dispatcher == null)
return;
var myTimer = new DispatcherTimer(
DispatcherPriority.Normal,
Application.Current.Dispatcher)
{
Interval = TimeSpan.FromSeconds(seconds)
};
myTimer.Tick += (_, _) =>
{
action?.Invoke();
myTimer.Stop();
};
myTimer.Start();
}
}
WpfUtils.RunAfter(3, () =>
{
// some code
Console.WriteLine("Running after 3 seconds");
});
请注意,此代码将在 UI 线程上运行。另一方面,如果您使用
Task
类中的方法,则延迟的代码将在后台线程上运行。
Task.Delay(6 * 1000).ContinueWith(_ =>
{
// this will run in a background-thread
var b = Thread.CurrentThread.IsBackground;
Debug.Assert(b);
Console.WriteLine("3");
});
var timer = new DispatcherTimer
{
Interval = TimeSpan.FromSeconds(3)
};
timer.Tick += (_, _) =>
{
// this will run in the UI-thread
var b = Thread.CurrentThread.IsBackground;
Debug.Assert(!b);
Console.WriteLine("2");
timer.Stop();
};
timer.Start();
Console.WriteLine("1");
// output
// 1
// 2
// 3
我用的是这个方法:
Timer
拖至表单并设置 Enabled=False
和 Interval=YOUR_DELAY
Timer1.Enabled = false
!Timer1.Enabled = true
因此,当您单击按钮或某物时,计时器就会启动,并且在运行代码后,它将再次被禁用。