LOGO OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 开发文档 其他文档  
 
网站管理员

你真的会使用C#中的异步Void方法吗?

admin
2024年6月5日 23:58 本文热度 1042

概述:async void对于许多开发人员来说,C# 中的方法是编写异步 await 代码时出现许多问题的根源。我们建议使用的模式当然是 ,但在某些情况下(例如 C# 中的事件处理程序),方法签名不兼容。async Task在本文中,我将解释为什么 C# 中的方法是你要避免的。我们将介绍一些比较和更好地理解的代码示例,我还将解释如果您别无选择,只能执行 .async voidasync voidasync Taskasync voidC# 中的异步 void 方法是什么?在 C# 中,方法是一种定义不返回值的异步方法的方法。这些方法通常用于事件处理程序或其他方案,在这些方案中,强制实施的方法签名不支

async void对于许多开发人员来说,C# 中的方法是编写异步 await 代码时出现许多问题的根源。我们建议使用的模式当然是 ,但在某些情况下(例如 C# 中的事件处理程序),方法签名不兼容。async Task

在本文中,我将解释为什么 C# 中的方法是你要避免的。我们将介绍一些比较和更好地理解的代码示例,我还将解释如果您别无选择,只能执行 .async voidasync voidasync Taskasync void

C# 中的异步 void 方法是什么?

在 C# 中,方法是一种定义不返回值的异步方法的方法。这些方法通常用于事件处理程序或其他方案,在这些方案中,强制实施的方法签名不支持返回类型,而是强制执行。async voidTaskvoid

async void方法是在方法签名之前使用关键字,后跟返回类型来定义方法。例如:asyncvoid

public async void SomeMethod()  
{  
   // Code here  
}

与返回 或 的常规异步方法相比,有一些重要的区别需要注意。当我说“重要”时,我的意思是“你真的需要尽可能地避免这种情况,这样你就可以省去一些麻烦”。TaskTask<T>

CSharp 中的异步 void 和异步任务之间的区别

方法和方法之间的主要区别之一在于如何处理异常。async voidasync Task

在方法中,发生的任何异常都由返回的对象捕获。这允许调用代码处理异常或等待稍后观察任何异常。这就是在 C# 中构建整个异步 await 基础结构的方式。这通常就是为什么你会看到异步 await 被引入代码库,然后所有的调用代码开始被转换为异步 await 的原因——你真的希望它在那里。async TaskTaskTask

另一方面,方法不能直接等待,其中发生的任何异常都会冒泡到......哪里?首先启动 async 方法的 SynchronizationContext。甚至Microsoft的Stephen Cleary在他的文章中也提到:async void

使用异步 void 方法时,没有 Task 对象,因此从异步 void 方法引发的任何异常都将直接在异步 void 方法启动时处于活动状态的 SynchronizationContext 上引发。图 2 说明了无法自然捕获从异步 void 方法引发的异常。

C 语言中 async Task 与 async void 方法的代码示例#

使用每种模式比较相同代码布局的两种变体,以了解问题是如何产生的,这将很有帮助。请考虑以下使用 async Task 的示例:

public async Task ProcessDataAsync()  
{  
   // Some asynchronous operations  
}  
 
public async void HandleButtonClick(object sender, EventArgs e)  
{  
   try  
   {  
       await ProcessDataAsync();  
   }  
   catch (Exception ex)  
   {  
       // Handle the exception  
   }  
}

在此代码中,如果事件处理程序方法中发生异常,则该异常将被方法中的 try-catch 块捕获,并且可以适当地处理。但是,如果定义为相反,则引发的任何异常都将绕过事件处理程序方法中的 catch 块,并可能使应用程序崩溃:ProcessDataAsyncHandleButtonClickProcessDataAsyncasync voidProcessDataAsyncHandleButtonClick

public async void ProcessDataAsync()  
{  
   // Some asynchronous operations  
}  
 
public async void HandleButtonClick(object sender, EventArgs e)  
{  
   try  
   {  
       ProcessDataAsync();  
   }  
   catch (Exception ex)  
   {  
       // This will never catch the async exceptions!  
   }  
}

C# 语言中异步 void 方法的危险

你希望在本文中注意到的共同主题是,C# 中的方法是危险的,你应该尽量避免。以下是我们在使用方法时遇到的挑战列表,希望能引导您远离使用它们(除非您别无选择):async voidasync void

  1. 错误传播:方法不允许捕获或传播错误。当此类方法中发生异常时,它会逃逸到同步上下文,这通常会导致未经处理的异常,从而导致应用程序崩溃。async void

  2. 等待行为:与方法不同,方法不能等待。这可能会导致控制异步操作流的问题,从而可能导致争用条件或执行超出预期顺序的操作。async Taskasync void

  3. 调试难度:调试方法中的异常更具挑战性,因为调用堆栈可能无法准确表示引发异常时的执行流,从而使识别和修复 bug 的过程复杂化。async void

在 C# 语言中处理异步 void 方法的最佳实践

在 C# 中使用异步 void 方法时,请务必了解它们的潜在危险并遵循最佳实践,以确保代码库健壮可靠。以下是谨慎处理异步 void 方法的一些建议:

  1. 尽可能避免:通常应避免使用方法,尤其是在异常处理和错误恢复至关重要的情况下。虽然异步 void 方法可能看起来很方便,但它们缺乏传播异常的能力,并且可能导致不可预测的程序行为。相反,请考虑使用提供更好错误处理功能的方法。async voidasync voidasync Task

  2. 改用:通过对异步方法使用返回类型,可以利用 Task 的内置异常处理机制。这使您能够适当地捕获和处理异常,从而确保代码保持对执行流的控制。使用方法还可以实现更好的代码可维护性、可测试性,并且比 .async Taskasync Taskasync Taskasync void

  3. 处理方法中的异常:如果必须使用方法,请务必正确处理异常,以防止它们以静默方式传播并导致意外的系统行为。实现此目的的一种方法是将代码包含在 try/catch 块中。在 catch 块中,您可以记录异常并相应地处理它,例如向用户显示错误消息或回滚任何相关操作。async voidasync void

  4. 记录和监视异步操作:使用方法时,日志记录和监视变得更加重要。由于这些方法没有返回类型,因此确定其完成情况或识别任何潜在问题变得具有挑战性。实施可靠的日志记录和监视系统(例如使用 Serilog 等日志记录框架或利用 Application Insights)可以帮助跟踪异步操作的进度和状态,从而帮助进行调试和故障排除。async void

C# 中异步 void 方法的 Try/Catch

我之前写过几种不同的方法来尝试使用这种代码,但最终感觉确保将每个方法主体包装在 try/catch 中是最直接的。也许有人可以创建一个 Rosyln 分析器来强制执行这一点?async void

下面是一个示例,演示了如何在整个代码主体中使用 try-catch:async void

public async void DoSomethingAsync()  
{  
   try  
   {  
       // Perform asynchronous operations  
       await Task.Delay(1000);  
       await SomeAsyncMethod();  
   }  
   catch (Exception ex)  
   {  
       // **TODO:** ... whatever you need to do to properly report  
       // on issues in your async void calls so that you  
       // can debug them more effectively.  
 
       // Log the exception and handle it appropriately  
       Logger.Error(ex, "An error occurred while executing DoSomethingAsync");  
       // Display an error message or take necessary action  
       DisplayErrorMessage("Oops! Something went wrong. Please try again later.");  
   }  
}

通过遵守这些最佳实践,您可以降低与方法相关的风险,并避免一堆永无止境的头痛。请记住,尽可能优先使用方法,以便更好地处理异常并控制异步执行流 - 除非是绝对的最后手段,_否则您真的_不想在任何地方添加。async voidasync Taskasync void

由于多种原因,C# 中的方法可能很危险,您需要优先考虑不使用它们。在某些情况下,API 和方法签名(例如事件处理程序)不一致,但除此之外,请尽最大努力避免这些情况。

通过使用 ,我们失去了正确等待或处理异常的能力。这可能会导致代码中出现未经处理的异常和意外行为。为了避免这些危险,我建议您尽可能使用旨在异步的方法。这使我们能够等待结果,处理异常,并更好地控制代码的执行流。它促进了更好的错误处理并提高了整体代码质量。当您别无选择时,请确保将整个异步 void 方法包装在 try/catch 中,并投资于适当的错误处理/日志记录/报告。


该文章在 2024/6/5 23:58:42 编辑过
关键字查询
相关文章
正在查询...
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2024 ClickSun All Rights Reserved