📅  最后修改于: 2023-12-03 15:24:07.976000             🧑  作者: Mango
在 C# 编程中,我们经常需要等待一些耗时操作完成之后再继续执行其他代码,比如等待一个文件读取完成、等待一个网络请求返回、等待一个线程完成等。C# 提供了多种等待的方式,本文将对这些方式进行介绍。
async/await 是 C#5 新增的异步编程模型,它可以让我们在等待耗时操作的同时,不会阻塞当前线程,从而提高程序的响应性能。async/await 可以用于任何方法中,并且代码非常简洁易懂。下面是使用 async/await 的示例代码:
// async/await 示例代码
private async void Button_Click(object sender, RoutedEventArgs e)
{
// 耗时操作
await Task.Delay(1000);
// 继续执行其他代码
MessageBox.Show("Hello World!");
}
需要注意的是,为了使用 async/await,方法必须使用 async 关键字标记,返回类型必须是 Task 或 Taskawait
关键字等待异步操作完成,然后继续执行其他代码。
Task.WaitAll 可以等待多个任务完成后再继续执行其他代码。下面是使用 Task.WaitAll 的示例代码:
// Task.WaitAll 示例代码
private void Button_Click(object sender, RoutedEventArgs e)
{
Task task1 = Task.Factory.StartNew(() => {
// 耗时操作1
Thread.Sleep(1000);
});
Task task2 = Task.Factory.StartNew(() => {
// 耗时操作2
Thread.Sleep(2000);
});
Task.WaitAll(task1, task2);
// 继续执行其他代码
MessageBox.Show("Hello World!");
}
需要注意的是,Task.WaitAll 会阻塞当前线程,因此不能在 UI 线程中使用。
Task.Run 可以将耗时操作放到后台线程中执行,并在后台线程完成后返回一个代表完成状态的 Task 对象。下面是使用 Task.Run 的示例代码:
// Task.Run 示例代码
private void Button_Click(object sender, RoutedEventArgs e)
{
Task task = Task.Run(() =>
{
// 耗时操作
Thread.Sleep(1000);
});
task.Wait();
// 继续执行其他代码
MessageBox.Show("Hello World!");
}
和 Task.WaitAll 一样,Task.Run 会阻塞当前线程,因此也不能在 UI 线程中使用。
ManualResetEvent 是一个同步对象,它可以在多个线程之间同步信号和状态,以达到等待操作完成的效果。使用 ManualResetEvent 时,需要在耗时操作完成后调用 Set 方法,通知等待的线程继续执行。下面是使用 ManualResetEvent 的示例代码:
// ManualResetEvent 示例代码
private void Button_Click(object sender, RoutedEventArgs e)
{
ManualResetEvent manualEvent = new ManualResetEvent(false);
Task task = Task.Factory.StartNew(() =>
{
// 耗时操作
Thread.Sleep(1000);
// 通知 ManualResetEvent
manualEvent.Set();
});
// 等待 ManualResetEvent
manualEvent.WaitOne();
// 继续执行其他代码
MessageBox.Show("Hello World!");
}
需要注意的是,ManualResetEvent 可以在任意线程中使用,但也会阻塞当前线程。
CountdownEvent 是一个同步对象,它可以在多个线程之间同步信号和状态,以达到等待操作完成的效果。和 ManualResetEvent 不同的是,CountdownEvent 可以等待多个操作完成之后再继续执行。下面是使用 CountdownEvent 的示例代码:
// CountdownEvent 示例代码
private void Button_Click(object sender, RoutedEventArgs e)
{
CountdownEvent countdownEvent = new CountdownEvent(2);
Task task1 = Task.Factory.StartNew(() =>
{
// 耗时操作1
Thread.Sleep(1000);
// 通知 CountdownEvent
countdownEvent.Signal();
});
Task task2 = Task.Factory.StartNew(() =>
{
// 耗时操作2
Thread.Sleep(2000);
// 通知 CountdownEvent
countdownEvent.Signal();
});
// 等待 CountdownEvent
countdownEvent.Wait();
// 继续执行其他代码
MessageBox.Show("Hello World!");
}
需要注意的是,CountdownEvent 也可以在任意线程中使用,但也会阻塞当前线程。
本文介绍了 C# 中常用的等待方式,包括 async/await、Task.WaitAll、Task.Run、ManualResetEvent 和 CountdownEvent。根据不同的场景需求,可以选择不同的等待方式来优化程序的性能和响应速度。