📜  如何在 c# 中等待(1)

📅  最后修改于: 2023-12-03 15:24:07.976000             🧑  作者: Mango

如何在 C# 中等待

在 C# 编程中,我们经常需要等待一些耗时操作完成之后再继续执行其他代码,比如等待一个文件读取完成、等待一个网络请求返回、等待一个线程完成等。C# 提供了多种等待的方式,本文将对这些方式进行介绍。

1. async/await

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 或 Task。方法内部通过 await 关键字等待异步操作完成,然后继续执行其他代码。

2. Task.WaitAll

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 线程中使用。

3. Task.Run

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 线程中使用。

4. ManualResetEvent

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 可以在任意线程中使用,但也会阻塞当前线程。

5. CountdownEvent

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。根据不同的场景需求,可以选择不同的等待方式来优化程序的性能和响应速度。