nos*_*tio 145 c# async-await
这不是"如何在没有等待的情况下安全地调用C#中的异步方法"的副本.
我如何很好地抑制以下警告?
警告CS4014:由于未等待此调用,因此在完成调用之前,将继续执行当前方法.考虑将'await'运算符应用于调用的结果.
一个简单的例子:
static async Task WorkAsync()
{
await Task.Delay(1000);
Console.WriteLine("Done!");
}
static async Task StartWorkAsync()
{
WorkAsync(); // I want fire-and-forget
// more unrelated async/await stuff here, e.g.:
// ...
await Task.Delay(2000);
}
Run Code Online (Sandbox Code Playgroud)
我尝试过但不喜欢的事情:
static async Task StartWorkAsync()
{
#pragma warning disable 4014
WorkAsync(); // I want fire-and-forget here
#pragma warning restore 4014
// ...
}
static async Task StartWorkAsync()
{
var ignoreMe = WorkAsync(); // I want fire-and-forget here
// ...
}
Run Code Online (Sandbox Code Playgroud)
更新后,由于原始接受的答案已被编辑,我已将已接受的答案更改为使用C#7.0丢弃的答案,因为我认为ContinueWith这不合适.每当我需要记录"即发即弃"操作的异常时,我就会使用Stephen Cleary提出的更精细的方法.
Ant*_*ser 136
使用C#7,您现在可以使用丢弃:
_ = WorkAsync();
Run Code Online (Sandbox Code Playgroud)
Kna*_*ģis 120
您可以创建一个阻止警告的扩展方法.扩展方法可以为空,也可以在.ContinueWith()那里添加异常处理.
static class TaskExtensions
{
public static void Forget(this Task task)
{
task.ContinueWith(
t => { WriteLog(t.Exception); },
TaskContinuationOptions.OnlyOnFaulted);
}
}
public async Task StartWorkAsync()
{
this.WorkAsync().Forget();
}
Run Code Online (Sandbox Code Playgroud)
但是,ASP.NET会计算正在运行的任务的数量,因此它不能与Forget()上面列出的简单扩展一起使用,而是可能会失败并出现异常:
在异步操作仍处于挂起状态时完成异步模块或处理程序.
使用.NET 4.5.2,可以使用HostingEnvironment.QueueBackgroundWorkItem以下方法解决:
public static Task HandleFault(this Task task, CancellationToken cancelToken)
{
return task.ContinueWith(
t => { WriteLog(t.Exception); },
cancelToken,
TaskContinuationOptions.OnlyOnFaulted,
TaskScheduler.Default);
}
public async Task StartWorkAsync()
{
System.Web.Hosting.HostingEnvironment.QueueBackgroundWorkItem(
cancelToken => this.WorkAsync().HandleFault(cancelToken));
}
Run Code Online (Sandbox Code Playgroud)
Fáb*_*bio 37
您可以使用以下属性修饰方法:
[System.Diagnostics.CodeAnalysis.SuppressMessage("Await.Warning", "CS4014:Await.Warning")]
static async Task StartWorkAsync()
{
WorkAsync();
// ...
}
Run Code Online (Sandbox Code Playgroud)
基本上你告诉编译器你知道你在做什么,而且不需要担心可能的错误.
这段代码的重要部分是第二个参数."CS4014:"部分是抑制警告的部分.你可以写下你想要的任何东西.
fjc*_*997 32
我的两种处理方式.
只是压制它
_ = Task.Run(() => DoMyStuff()).ConfigureAwait(false); 是一个很好的解决方案,"发射并忘记".
存在此警告的原因是因为在许多情况下,您不打算使用在不等待的情况下返回任务的方法.当你打算开火和忘记时,抑制警告是有道理的.
如果您无法记住如何拼写#pragma warning disable 4014,只需让Visual Studio为您添加即可.按Ctrl +.打开"快速操作"然后"抑制CS2014"
将其保存到本地变量
例
#pragma warning disable 4014
由于没有后续调用_ = Task.Run(() => DoMyStuff()).ConfigureAwait(false);,在Release模式下,本地变量应该立即优化,就像它从来没有那样.事实上,我怀疑编译器甚至会创建局部变量(有人可以用反编译器确认它).
总而言之
创建一个需要更多滴答来执行的方法是愚蠢的,只是为了抑制警告.
noe*_*cus 10
停止警告的一种简单方法是在调用时简单地分配任务:
Task fireAndForget = WorkAsync(); // No warning now
Run Code Online (Sandbox Code Playgroud)
所以在您的原始帖子中你会这样做:
static async Task StartWorkAsync()
{
// Fire and forget
var fireAndForget = WorkAsync(); // Tell the compiler you know it's a task that's being returned
// more unrelated async/await stuff here, e.g.:
// ...
await Task.Delay(2000);
}
Run Code Online (Sandbox Code Playgroud)
小智 8
警告的原因是 WorkAsync 返回的是Task从未读取或等待的值。您可以将 WorkAsync 的返回类型设置为void,警告就会消失。
Task通常,当调用者需要知道工作人员的状态时,方法会返回 a 。在“即发即弃”的情况下,应该返回 void 以表明调用者独立于被调用的方法。
static async void WorkAsync()
{
await Task.Delay(1000);
Console.WriteLine("Done!");
}
static async Task StartWorkAsync()
{
WorkAsync(); // no warning since return type is void
// more unrelated async/await stuff here, e.g.:
// ...
await Task.Delay(2000);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
44987 次 |
| 最近记录: |