四、C#高级特性(异步编程与Task)

发布时间:2024年01月05日

在C#中,异步编程和Task是两个非常重要的高级特性,它们可以帮助你编写更高效、更可伸缩的代码。下面是对这两个特性的详细介绍:

异步编程

异步编程允许你编写看起来像同步代码的代码,但实际上它是非阻塞的,可以继续执行其他任务而不必等待某个操作完成。这在处理I/O操作(如网络请求、文件读写等)时特别有用,因为这些操作通常需要等待很长时间。

C#提供了asyncawait关键字来支持异步编程。

async 关键字

在方法前使用async关键字标记该方法为异步。这意味着该方法可能会在执行期间挂起,让出控制权,以便其他代码可以运行。

public async Task MyAsyncMethod()
{
    // 异步操作
}
await 关键字

在方法内部,你可以使用await关键字来等待一个异步操作完成。这会暂停当前方法的执行,直到异步操作完成。

public async Task MyAsyncMethod()
{
    await Task.Delay(1000); // 等待1秒
    // 异步操作完成后继续执行这里
}

使用await时,你通常会看到一个返回TaskTask<T>的异步方法。例如,.NET内置的HttpClient类的GetAsync方法返回一个Task<HttpResponseMessage>

public async Task MyWebRequestMethod()
{
    HttpClient client = new HttpClient();
    HttpResponseMessage response = await client.GetAsync("http://example.com");
    // 处理响应...
}

Task 类型

在C#中,Task类型表示一个异步操作。它是.NET Framework 4.0引入的,用于简化异步编程模型。你可以使用Task.Run来执行一个同步方法作为异步任务,或者使用其他异步方法(如上面提到的HttpClient.GetAsync)。

创建和等待任务

你可以使用Task.Run来创建一个新的任务并立即开始执行它。然后可以使用Task.Waitawait来等待任务完成。

Task<int> task = Task.Run(() => SomeSynchronousMethod()); // 创建并立即开始任务
task.Wait(); // 等待任务完成(同步阻塞)
// 或者使用 await 关键字等待任务完成(异步非阻塞)
int result = await task; // 等待任务完成并获取结果(如果Task<T>返回了一个值)
Task状态和异常处理

你可以检查任务的Status属性来确定它的状态(如:NotStarted、Running、WaitingForChildrenToComplete、RanToCompletion、Canceled、Faulted)。你也可以使用Exception属性来获取和处理任务可能抛出的异常。

try
{
    await task; // 等待任务完成并捕获异常(如果任务失败)
}
catch (AggregateException ae) // 处理任务可能抛出的异常(当 await 表达式中存在多个 Task 时)或特定的异常类型。
{
    foreach (var innerException in ae.InnerExceptions)
    {
        // 处理异常...
    }
}
catch (Exception ex) // 处理特定类型的异常...
{
    // 处理异常...
}

异步方法的返回值

对于返回特定类型的异步方法,如上面提到的HttpClient.GetAsync,你通常会看到一个Task<T>的返回类型,其中T是返回的数据类型。这是因为异步方法需要返回一个Task对象来表示操作正在进行,而不仅仅是等待操作完成。当操作完成时,返回的Task对象将包含结果数据。

异常处理

在异步编程中,异常处理是一个重要的方面。由于异步操作可能会在任何时候完成或抛出异常,因此在编写异步代码时,你需要确保正确处理所有可能的异常情况。

使用try-catch块来捕获和处理异常是一个常见的做法。与同步代码不同,当使用await关键字时,异常会被自动捕获,并且可以在catch块中处理。

任务调度器(Task Scheduler)

任务调度器是决定如何以及何时运行任务的部分。C#中默认的任务调度器是TaskScheduler.Default,它是基于线程池的。这意味着当你使用Task.Run来创建并运行一个任务时,该任务会在一个线程池线程上执行。

除了默认的线程池调度器外,还有其他的任务调度器可供选择,如TaskScheduler.FromCurrentSynchronizationContext或自定义的调度器。选择适当的任务调度器取决于你的应用程序的具体需求。

结论

C#的异步编程和Task类型提供了强大的工具,可以帮助你编写更高效、更可伸缩的代码。通过合理地使用这些特性,你可以减少线程阻塞和提高应用程序的性能。

文章来源:https://blog.csdn.net/ww1457950571/article/details/135412932
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。