【发布时间】:2017-01-18 13:55:42
【问题描述】:
我在将 ASP.NET 应用程序迁移到 async/await 模型时偶然发现了一个相当危险的场景。
情况是我做了一个方法async:async Task DoWhateverAsync(),把接口中的声明改成Task DoWhateverAsync(),希望编译器能告诉我现在代码哪里错了,通过that Warning。好吧,运气不好。无论该对象通过接口注入到何处,都不会发生警告。 :-(
这很危险。有没有办法自动检查返回任务的非等待方法?我不介意警告太多,但我不想错过任何一个。
这是一个例子:
using System.Threading.Tasks;
namespace AsyncAwaitGames
{
// In my real case, that method just returns Task.
public interface ICallee { Task<int> DoSomethingAsync(); }
public class Callee: ICallee
{
public async Task<int> DoSomethingAsync() => await Task.FromResult(0);
}
public class Caller
{
public void DoCall()
{
ICallee xxx = new Callee();
// In my real case, the method just returns Task,
// so there is no type mismatch when assigning a result
// either.
xxx.DoSomethingAsync(); // This is where I had hoped for a warning.
}
}
}
【问题讨论】:
-
它可能不像编译器警告那样通用,但我通常依赖于返回类型。如果我希望某个东西是
string并尝试将其用作string,但实际上它是Task<string>,编译器将告诉我这一点。 (我猜对void/Task没有帮助。) -
"之前的声明是什么?"不幸的是,它是无效的,并改为任务。
-
我不了解您的情况。你说“希望编译器能告诉我现在的代码哪里错了”。
await是程序中的一个点,等待的继续逻辑上需要完成任务。更改之前的代码在逻辑上不需要完成任务,那么为什么要在更改之后现在呢?引入了什么错误? -
我更改之前的代码/假设/完成了任务,因为 DoSomething() 是一个返回 void 的同步方法。然后我将方法更改为异步并返回任务。如果我直接使用该类,Visual Studio 会给我一个警告。由于我无法在上面的 ICallee 中将“异步”添加到方法签名中,因此代码现在看起来像返回 Task 的普通方法。显然这不足以触发 a) 使 DoCall() 异步和 b) 等待 xxx.DoSomethingAsync() 的警告。这是可以理解的。对我来说,根本原因是我无法在 ICallee 中指定“异步”。
-
"引入了什么错误?"之前:
public void DoCall() { ICallee xxx = new Callee(); xxx.DoSomething();}(好)。之后:public void DoCall() { ICallee xxx = new Callee(); xxx.DoSomethingAsync();}(坏)。好:public void DoCall() { ICallee xxx = new Callee(); await xxx.DoSomethingAsync();}
标签: c# async-await