首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在C#中安全调用异步方法而不等待

如何在C#中安全调用异步方法而不等待
EN

Stack Overflow用户
提问于 2013-03-20 11:59:06
回答 13查看 342.6K关注 0票数 460

我有一个不返回数据的async方法:

代码语言:javascript
运行
复制
public async Task MyAsyncMethod()
{
    // do some stuff async, don't return any data
}

我从另一个方法调用它,它返回一些数据:

代码语言:javascript
运行
复制
public string GetStringData()
{
    MyAsyncMethod(); // this generates a warning and swallows exceptions
    return "hello world";
}

在没有等待的情况下调用MyAsyncMethod()会导致visual中的"因为没有等待此调用,因此在调用完成之前,当前方法将继续运行。“警告。在该警告的页面上,它指出:

只有当您确信不希望等待异步调用完成,并且被调用的方法不会引发任何异常时,才应该考虑取消警告。

我确信我不想等待电话的完成,我不需要也没有时间去做。,但是调用可能会引起异常。

我偶然遇到过这个问题几次,我相信这是一个共同的问题,必须有一个共同的解决办法。

如何安全地调用异步方法而不等待结果?

更新:

对于那些建议我只是等待结果的人来说,这是响应web服务上的web请求的代码(ASP.NET Web )。在UI上下文中等待使UI线程保持空闲,但是等待在web请求调用中等待任务完成后才会响应请求,从而增加响应时间。

EN

回答 13

Stack Overflow用户

回答已采纳

发布于 2013-03-20 12:59:55

如果您想获得“异步”异常,可以:

代码语言:javascript
运行
复制
  MyAsyncMethod().
    ContinueWith(t => Console.WriteLine(t.Exception),
        TaskContinuationOptions.OnlyOnFaulted);

这将允许您在“主”线程之外的线程上处理异常。这意味着您不必从调用MyAsyncMethod()的线程中“等待”调用MyAsyncMethod;但是,仍然允许您处理异常--但只有在出现异常时才能这样做。

更新:

从技术上讲,您可以使用await进行类似的操作。

代码语言:javascript
运行
复制
try
{
    await MyAsyncMethod().ConfigureAwait(false);
}
catch (Exception ex)
{
    Trace.WriteLine(ex);
}

如果您需要具体使用try/catch (或using),那么try会很有用,但是我发现ContinueWith更明确一些,因为您必须知道ConfigureAwait(false)是什么意思。

票数 270
EN

Stack Overflow用户

发布于 2013-03-20 12:39:02

首先,您应该考虑让GetStringData成为一个async方法,并让它awaitMyAsyncMethod返回的任务。

如果您完全确定不需要处理MyAsyncMethod的异常或知道它何时完成,那么您可以这样做:

代码语言:javascript
运行
复制
public string GetStringData()
{
  var _ = MyAsyncMethod();
  return "hello world";
}

顺便说一句,这不是一个“常见的问题”。很少有人想要执行一些代码,而不关心它是否完成,而不关心它是否成功完成。

更新:

既然你在ASP.NET上,想早点回来,你可能会找到我的关于这个主题的博客文章很有用。但是,ASP.NET并不是为此而设计的,并且不能保证您的代码会在返回响应后运行。ASP.NET将尽最大努力让它运行,但它不能保证它运行。

因此,对于一些简单的问题来说,这是一个很好的解决方案,比如将一个事件扔到日志中,如果您在这里和那里丢失一些并不重要的地方,那么这是一个很好的解决方案。对于任何类型的关键业务操作,它都不是一个好的解决方案。在这些情况下,您必须采用更复杂的体系结构,使用持久的方法保存操作(例如,Azure队列、MSMQ)和单独的后台进程(例如,Azure Worker角色,Win32服务)来处理它们。

票数 94
EN

Stack Overflow用户

发布于 2013-03-20 15:49:46

彼得·里奇( Peter )的回答是我想要的,而斯蒂芬·克利里的文章关于在ASP.NET早期返回的想法非常有帮助。

然而,作为一个更普遍的问题(不是特定于ASP.NET上下文),下面的控制台应用程序演示了使用Task.ContinueWith(...)的Peter的答案的用法和行为

代码语言:javascript
运行
复制
static void Main(string[] args)
{
  try
  {
    // output "hello world" as method returns early
    Console.WriteLine(GetStringData());
  }
  catch
  {
    // Exception is NOT caught here
  }
  Console.ReadLine();
}

public static string GetStringData()
{
  MyAsyncMethod().ContinueWith(OnMyAsyncMethodFailed, TaskContinuationOptions.OnlyOnFaulted);
  return "hello world";
}

public static async Task MyAsyncMethod()
{
  await Task.Run(() => { throw new Exception("thrown on background thread"); });
}

public static void OnMyAsyncMethodFailed(Task task)
{
  Exception ex = task.Exception;
  // Deal with exceptions here however you want
}

GetStringData()在没有等待MyAsyncMethod()的情况下提前返回,在MyAsyncMethod()中抛出的异常将在OnMyAsyncMethodFailed(Task task)中处理,而不是在GetStringData() /catch中处理

票数 59
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15522900

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档