.NET 帮助

C# ConfigureAwait(面向开发人员的工作原理)

Chipego
奇佩戈-卡琳达
2024年十月24日
分享:

作为一名开发人员,异步编程是非常有益的,它可以提高应用程序的性能、效率和响应速度,尤其是那些需要花费大量时间才能完成的操作。 通过使用`ConfigureAwait(false)`,您可以在某些场景下避免死锁。 当在异步编程中出现死锁时,是因为存在一个同步上下文(例如桌面应用程序中的UI线程),该上下文期望某个操作在继续之前完成。 但是,等待的任务仍在等待同步上下文可用,这就造成了循环等待。

今天,我们将探讨如何使用ConfigureAwait和IronPDF通过异步编程高效地执行PDF处理任务。 IronPDF for .NET 是一个.NET PDF 库,可让处理 PDF 相关任务变得轻而易举。 凭借强大的功能集、强大的跨平台兼容性和丰富的文档,它是开发人员工具包中不可或缺的强大 PDF 工具。

了解 C# 异步编程;

什么是异步编程?

异步编程是指允许某些操作独立于主应用程序线程运行的代码编写方法。 这对于需要等待的长时间运行任务(如 I/O 操作)非常有用。 通过允许这些任务在不阻塞主线程的情况下运行,应用程序可以在这些任务需要时间完成时继续运行,最终提高应用程序的性能和响应速度。

ConfigureAwait 在异步代码中的作用

ConfigureAwait 是异步编程中的一种方法,用于控制延续的执行方式。 在默认情况下,**await** 表达式之后运行的代码是 continuation,**await** 会捕获当前上下文并尝试将 continuation 返回到该上下文,这可能效率不高。ConfigureAwait 允许你指定 continuation 是否应在捕获的上下文中运行,用 **ConfigureAwait(true)** 表示,或不在该上下文中运行,用 **ConfigureAwait(false)** 表示。

使用`ConfigureAwait(false)`有助于避免死锁,这是因为当您使用它时,您是在告诉任务不要捕获当前的同步上下文,也不要尝试在原始上下文上恢复。 这样就可以在线程池线程上而不是在原始上下文中继续运行,从而防止主线程被阻塞。

`ConfigureAwait(false)` 尤其在库代码或不需要恢复原始上下文的情况下特别有用,从而确保代码保持灵活性并避免死锁。

如何将 ConfigureAwait 与 IronPdf 结合使用

在您的 .NET 项目中设置 IronPDF

要在您的.NET项目中开始使用IronPDF,首先需安装IronPDF NuGet 包。 您可以通过导航至工具 > NuGet Package Manager > NuGet Package Manager for Solution 并搜索 IronPdf 来完成:

C# ConfigureAwait(对开发者的工作原理):图1

或在软件包管理器控制台中运行以下命令:

Install-Package IronPdf
Install-Package IronPdf
'INSTANT VB TODO TASK: The following line uses invalid syntax:
'Install-Package IronPdf
$vbLabelText   $csharpLabel

要开始在代码中使用IronPDF,请确保已在代码文件的顶部放置了`using IronPdf`语句。有关在您的环境中设置IronPDF的更深入指南,请查看其入门页面。

使用 IronPDF 异步生成 PDFs

异步生成 PDF 文件在需要生成大量 PDF 文件或希望同时执行多个操作的情况下尤其有益。 使用 IronPDF,您可以异步执行与 PDF 相关的任务,这可能类似于下面的异步代码:

using IronPdf;
using System.Threading.Tasks;
class program
{
    static async Task Main(string[] args)
    {
        await GeneratePdfAsync();
    }
    static async Task GeneratePdfAsync()
    {
        ChromePdfRenderer renderer = new ChromePdfRenderer();
        string htmlContent = "<h1>Hello World!</h1>";
        PdfDocument pdf = await renderer.RenderHtmlAsPdfAsync(htmlContent);
        await Task.Run(() => pdf.SaveAs("outputAsync.pdf"));
        Console.WriteLine("Working!");
    }
}
using IronPdf;
using System.Threading.Tasks;
class program
{
    static async Task Main(string[] args)
    {
        await GeneratePdfAsync();
    }
    static async Task GeneratePdfAsync()
    {
        ChromePdfRenderer renderer = new ChromePdfRenderer();
        string htmlContent = "<h1>Hello World!</h1>";
        PdfDocument pdf = await renderer.RenderHtmlAsPdfAsync(htmlContent);
        await Task.Run(() => pdf.SaveAs("outputAsync.pdf"));
        Console.WriteLine("Working!");
    }
}
Imports IronPdf
Imports System.Threading.Tasks
Friend Class program
	Shared Async Function Main(ByVal args() As String) As Task
		Await GeneratePdfAsync()
	End Function
	Private Shared Async Function GeneratePdfAsync() As Task
		Dim renderer As New ChromePdfRenderer()
		Dim htmlContent As String = "<h1>Hello World!</h1>"
		Dim pdf As PdfDocument = Await renderer.RenderHtmlAsPdfAsync(htmlContent)
		Await Task.Run(Function() pdf.SaveAs("outputAsync.pdf"))
		Console.WriteLine("Working!")
	End Function
End Class
$vbLabelText   $csharpLabel

在此代码中,我们在 GeneratePdfAsync() 方法中异步创建了一个 PDF 文档。 ChromePdfRenderer 用于创建渲染器,这是从 HTML 内容生成 PDF 文件的关键。 PdfDocument 类用于从提供的 HTML 字符串 创建 PDF,不过,您也可以用它从 HTML 文件URL图像 等创建 PDF。 有关使用IronPDF生成PDF的不同方法的更多信息,请查看如何生成PDF部分

异步处理大型 PDF 文件

在处理大型 PDF 文件时,使用异步方法并结合`ConfigureAwait(false)`可以通过在长时间操作期间释放主线程来显著提高性能。 在此示例中,我选取了一个大型 PDF 文档,并执行了文本提取任务,以演示异步 PDF 处理的好处。

using IronPdf;
using System.Threading.Tasks;
using System.IO;
using System;
class Program
{
    static async Task Main(string[] args)
    {
        await LongPdfTask();
    }
    static async Task LongPdfTask()
    {
        try
        {
            // Initialize IronPDF's PdfDocument
            PdfDocument pdf = await Task.Run(() => PdfDocument.FromFile("Sample.pdf")).ConfigureAwait(false);
            // Extract text from PDF asynchronously
            string text = await Task.Run(() => pdf.ExtractAllText()).ConfigureAwait(false);
            // Write the extracted text to a file asynchronously
            await Task.Run(() => File.WriteAllText("extractedText.txt", text)).ConfigureAwait(false);
            Console.WriteLine("Extraction complete!");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error in GeneratePdfAsync: {ex.Message}");
        }
    }
}
using IronPdf;
using System.Threading.Tasks;
using System.IO;
using System;
class Program
{
    static async Task Main(string[] args)
    {
        await LongPdfTask();
    }
    static async Task LongPdfTask()
    {
        try
        {
            // Initialize IronPDF's PdfDocument
            PdfDocument pdf = await Task.Run(() => PdfDocument.FromFile("Sample.pdf")).ConfigureAwait(false);
            // Extract text from PDF asynchronously
            string text = await Task.Run(() => pdf.ExtractAllText()).ConfigureAwait(false);
            // Write the extracted text to a file asynchronously
            await Task.Run(() => File.WriteAllText("extractedText.txt", text)).ConfigureAwait(false);
            Console.WriteLine("Extraction complete!");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error in GeneratePdfAsync: {ex.Message}");
        }
    }
}
Imports IronPdf
Imports System.Threading.Tasks
Imports System.IO
Imports System
Friend Class Program
	Shared Async Function Main(ByVal args() As String) As Task
		Await LongPdfTask()
	End Function
	Private Shared Async Function LongPdfTask() As Task
		Try
			' Initialize IronPDF's PdfDocument
			Dim pdf As PdfDocument = Await Task.Run(Function() PdfDocument.FromFile("Sample.pdf")).ConfigureAwait(False)
			' Extract text from PDF asynchronously
			Dim text As String = Await Task.Run(Function() pdf.ExtractAllText()).ConfigureAwait(False)
			' Write the extracted text to a file asynchronously
			Await Task.Run(Sub() File.WriteAllText("extractedText.txt", text)).ConfigureAwait(False)
			Console.WriteLine("Extraction complete!")
		Catch ex As Exception
			Console.WriteLine($"Error in GeneratePdfAsync: {ex.Message}")
		End Try
	End Function
End Class
$vbLabelText   $csharpLabel

在上述代码中,`ConfigureAwait(false)` 用于从一个大型 PDF 文件中提取所有文本的耗时任务中,在我们的例子中,该文件超过200页。

  • 导入和设置:我们代码顶部的第一个部分专注于导入必要的库和命名空间。 您需要确保使用 `using IronPdf` 来使用 IronPDF 库
  • 类和主方法: `class Program` 定义了包含此项目的主要应用程序代码的类。 `static async Task Main(string[] args)` 是应用程序的入口点。 在这里,我们将其标记为async,这样我们的异步操作可以在其中运行。 然后,我们使用await LongPdfTask()异步调用LongPdfTask方法。
  • 尝试块:我已将代码包含在LongPdfTask方法中,并在try-catch块中包装,以优雅地处理任何意外异常。

    • PdfDocument PDF = await Task.Run(() => PdfDocument.FromFile("Sample.pdf")).ConfigureAwait(false): 这一行可以分解为三个不同的部分:

      • PdfDocument.FromFile("Sample.pdf"): 此部分将指定的 PDF 文件同步加载到 IronPdf.PdfDocument 对象中。

      • await Task.Run(() => ...): 在单独的线程上运行 PDF 加载操作,以避免阻塞主线程。 因此,这是一项异步工作。
  • .ConfigureAwait(false): 避免捕获当前上下文,这应该可以提高性能并减少死锁。
  • string text = await Task.Run(() => pdf.ExtractAllText()).ConfigureAwait(false): 这将运行 IronPDF 文本提取 方法,ExtractAllText()。 再次,await Task.Run(() => ...) 用于在单独的线程上异步运行此操作。
  • await Task.Run(() => File.WriteAllText("extractedText.txt", text)).ConfigureAwait(false):通过此方法,我们再次使用await Task方法异步将提取的文本写入.txt文件。

之前

C# ConfigureAwait(开发人员如何使用):图 2

输出

C# ConfigureAwait(它如何为开发者工作):图3

在 .NET 应用程序中使用 ConfigureAwait 的最佳实践

何时使用 ConfigureAwait(true) 与 ConfigureAwait(false)

ConfigureAwait(false) 最适合在库代码或后台处理时使用,这里不需要保留同步上下文。 通常,这是针对性能至关重要的服务器端代码。 使用ConfigureAwait(false)意味着当await操作完成时,后续操作不一定在启动异步操作的同一线程上运行。

在 PDF 处理方面,实施ConfigureAwait(false)可以在运行多个 PDF 处理任务时帮助最大化性能,以避免因上下文切换而导致的瓶颈。 在处理大量 PDF 文件时,它还能帮助应用程序保持流畅运行;在控制台应用程序或后台服务中工作时,上下文切换可能没有必要,它也能帮助保持效率。

ConfigureAwait(true) 最适用于用户界面、代码的任何单元测试或ASP.NET应用程序,其中延续必须在相同的上下文中运行,尽管如果使用不当可能导致死锁。 例如,如果您正在更新UI或访问httpcontext。 ConfigureAwait(true) 是默认行为,也可以简写为 ConfigureAwait

在处理PDF任务时,如果您的PDF处理代码与UI紧密集成(例如使用WPF、WinForms等UI应用程序),特别是在显示进度时,并且您需要捕获同步上下文以确保这些更新发生在UI线程上,这将特别有益。 在处理线程敏感的操作时,由于线程亲和性的要求,这些操作必须在特定的线程上执行,这也有利于翻译。

在异步 IronPDF 操作中处理异常

在异步编程中处理异常是需要牢记的一个重要方面,需要仔细考虑,未处理的异常可能会终止应用程序。 在异步代码中使用 try-catch 块是优雅地处理任何意外异常的好方法。

例如

public async Task SafeGeneratePdfAsync()
{
    try
    {
        ChromePdfRenderer renderer = new ChromePdfRenderer();
        PdfDocument pdf = await renderer.RenderHtmlAsPdfAsync("<h1>Error Handling</h1>").ConfigureAwait(false);
        await Task.Run(() => pdf.SaveAs("output.pdf")).ConfigureAwait(false);
    }
    catch (Exception ex)
    {
        Console.WriteLine($"An error occurred: {ex.Message}");
    }
}
public async Task SafeGeneratePdfAsync()
{
    try
    {
        ChromePdfRenderer renderer = new ChromePdfRenderer();
        PdfDocument pdf = await renderer.RenderHtmlAsPdfAsync("<h1>Error Handling</h1>").ConfigureAwait(false);
        await Task.Run(() => pdf.SaveAs("output.pdf")).ConfigureAwait(false);
    }
    catch (Exception ex)
    {
        Console.WriteLine($"An error occurred: {ex.Message}");
    }
}
Public Async Function SafeGeneratePdfAsync() As Task
	Try
		Dim renderer As New ChromePdfRenderer()
		Dim pdf As PdfDocument = Await renderer.RenderHtmlAsPdfAsync("<h1>Error Handling</h1>").ConfigureAwait(False)
		Await Task.Run(Function() pdf.SaveAs("output.pdf")).ConfigureAwait(False)
	Catch ex As Exception
		Console.WriteLine($"An error occurred: {ex.Message}")
	End Try
End Function
$vbLabelText   $csharpLabel

在使用`ConfigureAwait(false)`的延续任务时,可以在延续中使用try-catch处理异常,或者如果使用Task.ContinueWith,则可以通过Task.Exception属性处理异常。

如何编写代码的示例如下

class program
{
    public static async Task Main(string[] args)
    {
        await ProcessPdfWithContinuationAsync();
    }
    static Task ProcessPdfWithContinuationAsync()
    {
        return Task.Run(() => PdfDocument.FromFile("Sample.pdf"))
            .ContinueWith(pdfTask =>
            {
                if (pdfTask.IsFaulted)
                {
                    // Handle exceptions from loading the PDF
                    Console.WriteLine($"Error loading PDF: {pdfTask.Exception?.GetBaseException().Message}");
                    return;
                }
                var pdf = pdfTask.Result;
                // Extract text asynchronously with exception handling
                Task.Run(() => pdf.ExtractAllText())
                    .ContinueWith(extractTask =>
                    {
                        if (extractTask.IsFaulted)
                        {
                            // Handle exceptions from extracting text
                            Console.WriteLine($"Error extracting text: {extractTask.Exception?.GetBaseException().Message}");
                            return;
                        }
                        // Proceed if text extraction is successful
                        Console.WriteLine("Extracted text:");
                        Console.WriteLine(extractTask.Result);
                    }, TaskContinuationOptions.OnlyOnRanToCompletion);
            }, TaskContinuationOptions.OnlyOnRanToCompletion);
    }
class program
{
    public static async Task Main(string[] args)
    {
        await ProcessPdfWithContinuationAsync();
    }
    static Task ProcessPdfWithContinuationAsync()
    {
        return Task.Run(() => PdfDocument.FromFile("Sample.pdf"))
            .ContinueWith(pdfTask =>
            {
                if (pdfTask.IsFaulted)
                {
                    // Handle exceptions from loading the PDF
                    Console.WriteLine($"Error loading PDF: {pdfTask.Exception?.GetBaseException().Message}");
                    return;
                }
                var pdf = pdfTask.Result;
                // Extract text asynchronously with exception handling
                Task.Run(() => pdf.ExtractAllText())
                    .ContinueWith(extractTask =>
                    {
                        if (extractTask.IsFaulted)
                        {
                            // Handle exceptions from extracting text
                            Console.WriteLine($"Error extracting text: {extractTask.Exception?.GetBaseException().Message}");
                            return;
                        }
                        // Proceed if text extraction is successful
                        Console.WriteLine("Extracted text:");
                        Console.WriteLine(extractTask.Result);
                    }, TaskContinuationOptions.OnlyOnRanToCompletion);
            }, TaskContinuationOptions.OnlyOnRanToCompletion);
    }
Friend Class program
	Public Shared Async Function Main(ByVal args() As String) As Task
		Await ProcessPdfWithContinuationAsync()
	End Function
	Private Shared Function ProcessPdfWithContinuationAsync() As Task
		Return Task.Run(Function() PdfDocument.FromFile("Sample.pdf")).ContinueWith(Sub(pdfTask)
				If pdfTask.IsFaulted Then
					' Handle exceptions from loading the PDF
					Console.WriteLine($"Error loading PDF: {pdfTask.Exception?.GetBaseException().Message}")
					Return
				End If
				Dim pdf = pdfTask.Result
				' Extract text asynchronously with exception handling
				Task.Run(Function() pdf.ExtractAllText()).ContinueWith(Sub(extractTask)
						If extractTask.IsFaulted Then
							' Handle exceptions from extracting text
							Console.WriteLine($"Error extracting text: {extractTask.Exception?.GetBaseException().Message}")
							Return
						End If
						' Proceed if text extraction is successful
						Console.WriteLine("Extracted text:")
						Console.WriteLine(extractTask.Result)
				End Sub, TaskContinuationOptions.OnlyOnRanToCompletion)
		End Sub, TaskContinuationOptions.OnlyOnRanToCompletion)
	End Function
$vbLabelText   $csharpLabel

为什么选择 IronPDF 满足您的 PDF 处理需求?

IronPDF 的主要功能和优势

C# ConfigureAwait(其对开发人员的工作方式):图 4

IronPDF 是一个功能强大的 C# PDF 库,可为您的所有 PDF 相关任务提供丰富的功能。 IronPDF 完全支持 .NET8、7、6、.NET Core、Standard 和 Framework,并能在 Windows、Linux、Mac、Docker、Azure 和 AWS 等一系列应用程序环境中运行,无论您喜欢什么环境,都能最大限度地利用 IronPDF。

使用IronPDF,您可以从各种文件和数据类型生成PDF;包括HTML文件HTML字符串URL图像DOCXRTF,通常只需几行代码即可完成! 它可以处理您的PDF文档的格式,应用自定义水印合并和拆分PDF,处理PDF加密安全性,以及更多功能。

IronPDF 对异步编程的支持

IronPDF 为其许多操作提供异步方法,允许开发人员无缝利用异步/等待模式。 这种支持确保 IronPDF 可以集成到性能关键型应用程序中,而不会牺牲响应速度,使其成为在异步环境中工作的开发人员处理 PDF 相关任务的宝贵 PDF 工具。

许可

如果您想亲自尝试IronPDF并探索其广泛的功能,您可以利用其免费试用期轻松做到这一点。 IronPDF 的安装快捷简便,您很快就能在 PDF 项目中使用 IronPDF。想继续使用它并利用其强大的功能来提升您的 PDF 水平吗? 许可证起价仅为$749,并附有慷慨的30天退款保证、整整一年的产品支持和更新,并以永久许可证的形式提供(因此没有令人烦恼的经常性费用!)

C# ConfigureAwait(开发者如何使用):图5

示例:使用 ConfigureAwait 和 IronPDF 生成 PDF

为了异步生成PDF,我们将使用IronPDF执行代码来渲染HTML文件,并保存结果,同时使用ConfigureAwait(false)确保后续操作不会不必要地切换回原始同步上下文。

using IronPdf;
using System.Threading.Tasks;
using System.IO;
using System;
class program
{
    public static async Task Main(string[] args)
    {
        await CreateInvoicePdfAsync();
    }
    static async Task<string> CreateInvoicePdfAsync()
    {
        ChromePdfRenderer renderer = new ChromePdfRenderer();
        try
        {
            var pdf = await renderer.RenderHtmlFileAsPdfAsync("example.html").ConfigureAwait(false);
            await Task.Run(() => pdf.SaveAs("invoice.pdf")).ConfigureAwait(false);
            return filePath;
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error generating PDF: {ex.Message}");
            return null;
        }
    }
}
using IronPdf;
using System.Threading.Tasks;
using System.IO;
using System;
class program
{
    public static async Task Main(string[] args)
    {
        await CreateInvoicePdfAsync();
    }
    static async Task<string> CreateInvoicePdfAsync()
    {
        ChromePdfRenderer renderer = new ChromePdfRenderer();
        try
        {
            var pdf = await renderer.RenderHtmlFileAsPdfAsync("example.html").ConfigureAwait(false);
            await Task.Run(() => pdf.SaveAs("invoice.pdf")).ConfigureAwait(false);
            return filePath;
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error generating PDF: {ex.Message}");
            return null;
        }
    }
}
Imports IronPdf
Imports System.Threading.Tasks
Imports System.IO
Imports System
Friend Class program
	Public Shared Async Function Main(ByVal args() As String) As Task
		Await CreateInvoicePdfAsync()
	End Function
	Private Shared Async Function CreateInvoicePdfAsync() As Task(Of String)
		Dim renderer As New ChromePdfRenderer()
		Try
			Dim pdf = Await renderer.RenderHtmlFileAsPdfAsync("example.html").ConfigureAwait(False)
			Await Task.Run(Function() pdf.SaveAs("invoice.pdf")).ConfigureAwait(False)
			Return filePath
		Catch ex As Exception
			Console.WriteLine($"Error generating PDF: {ex.Message}")
			Return Nothing
		End Try
	End Function
End Class
$vbLabelText   $csharpLabel

在此示例中,我们使用创建的异步方法,static async TaskCreateInvoicePdfAsync(),从RenderHtmlFileAsPdfAsync方法提供的HTML文件生成PDF发票。 我们使用ConfigureAwait(false)来防止在原始同步上下文中继续执行此任务,从而提高了非UI应用程序的性能。

我们还再次实现了 await Task.Run(() => ...) 方法,以异步运行操作。 最后,我们使用 pdf.SaveAs 方法将新生成的 PDF 文件保存为“invoice.pdf”。 CreateInvoicePdfAsync()方法中的整个代码已包含在try-catch块中,以处理任何意外异常。

HTML 文件

C# ConfigureAwait(它如何为开发人员工作):图 6

输出

C# ConfigureAwait(开发者工作原理):图7

如您所见,我们成功地将 HTML 文件异步生成了 PDF,并为我们创建了一个清晰、高质量的 PDF 文件。

结论

异步编程对于构建响应迅速且高效的 .NET 应用程序至关重要,正确使用ConfigureAwait可以帮助您实现最佳性能,特别是在编写应用程序级代码时。 在使用IronPDF时,利用异步方法结合ConfigureAwait(false)可以确保您的PDF处理任务不会阻塞主线程,从而提高应用程序的整体响应能力。 通过了解何时以及如何使用ConfigureAwait,您可以使您的IronPDF PDF处理任务更健壮且性能更佳。

现在,您可以像专业人士一样利用ConfigureAwait与IronPDF进行异步编程,那么您还在等什么? 请立即试用 IronPDF,看看它如何提升您的 PDF 相关项目! 如果您想了解更多关于IronPDF作为强大的通用库代码所提供的各种功能,请务必查看其便捷的操作指南。 或者,如果您想了解更多关于将IronPDF与异步编程方法结合使用的信息,或者只是想更多了解IronPDF,请查看我们的博客文章。 如果您正在寻找更多异步PDF生成的示例,请查看我们的C# Wait For Seconds帖子或我们关于C# Task.Run的其他帖子

Chipego
软件工程师
Chipego 拥有出色的倾听技巧,这帮助他理解客户问题并提供智能解决方案。他在 2023 年加入 Iron Software 团队,此前他获得了信息技术学士学位。IronPDF 和 IronOCR 是 Chipego 主要专注的两个产品,但他对所有产品的了解每天都在增长,因为他不断找到支持客户的新方法。他喜欢 Iron Software 的合作氛围,公司各地的团队成员贡献他们丰富的经验,以提供有效的创新解决方案。当 Chipego 离开办公桌时,你经常可以发现他在看书或踢足球。
< 前一页
Azure 表(如何为开发人员工作)
下一步 >
C# 可空类型(如何为开发人员工作)