public Task<int> Success() // note: no "async"
{
... // non-awaiting code
int result = ...;
return Task.FromResult(result);
}
在抛出 NotImplementedException 的情况下,程序有点罗嗦:
public Task<int> Fail() // note: no "async"
{
var tcs = new TaskCompletionSource<int>();
tcs.SetException(new NotImplementedException());
return tcs.Task;
}
public async Task<object> test()
{
throw await new AwaitableNotImplementedException<object>();
}
这是我为了实现这一目的而添加的类型 .
public class AwaitableNotImplementedException<TResult> : NotImplementedException
{
public AwaitableNotImplementedException() { }
public AwaitableNotImplementedException(string message) : base(message) { }
// This method makes the constructor awaitable.
public TaskAwaiter<AwaitableNotImplementedException<TResult>> GetAwaiter()
{
throw this;
}
}
[RankColumn, MinColumn, MaxColumn, StdDevColumn, MedianColumn]
[ClrJob, CoreJob]
[HtmlExporter, MarkdownExporter]
[MemoryDiagnoser]
public class BenchmarkAsyncNotAwaitInterface
{
string context = "text context";
[Benchmark]
public int CompletedAwait()
{
var t = new CompletedAwaitTest();
var a = t.DoAsync(context);
a.Wait();
return t.Length;
}
[Benchmark]
public int Completed()
{
var t = new CompletedTest();
var a = t.DoAsync(context);
a.Wait();
return t.Length;
}
[Benchmark]
public int Pragma()
{
var t = new PragmaTest();
var a = t.DoAsync(context);
a.Wait();
return t.Length;
}
[Benchmark]
public int Yield()
{
var t = new YieldTest();
var a = t.DoAsync(context);
a.Wait();
return t.Length;
}
[Benchmark]
public int FromResult()
{
var t = new FromResultTest();
var t2 = t.DoAsync(context);
return t2.Result;
}
public interface ITestInterface
{
int Length { get; }
Task DoAsync(string context);
}
class CompletedAwaitTest : ITestInterface
{
public int Length { get; private set; }
public async Task DoAsync(string context)
{
Length = context.Length;
await Task.CompletedTask;
}
}
class CompletedTest : ITestInterface
{
public int Length { get; private set; }
public Task DoAsync(string context)
{
Length = context.Length;
return Task.CompletedTask;
}
}
class PragmaTest : ITestInterface
{
public int Length { get; private set; }
#pragma warning disable 1998
public async Task DoAsync(string context)
{
Length = context.Length;
return;
}
#pragma warning restore 1998
}
class YieldTest : ITestInterface
{
public int Length { get; private set; }
public async Task DoAsync(string context)
{
Length = context.Length;
await Task.Yield();
}
}
public interface ITestInterface2
{
Task<int> DoAsync(string context);
}
class FromResultTest : ITestInterface2
{
public async Task<int> DoAsync(string context)
{
var i = context.Length;
return await Task.FromResult(i);
}
}
}
-1
如果您已经链接到Reactive Extension,您还可以执行以下操作:
public async Task<object> NotImplemented()
{
await Observable.Throw(new NotImplementedException(), null as object).ToTask();
}
public async Task<object> SimpleResult()
{
await Observable.Return(myvalue).ToTask();
}
Reactive和async / await既令人惊叹又独立,但它们也能很好地协同工作 .
包括需要的是:
using System.Reactive.Linq;
using System.Reactive.Threading.Tasks;
7
它可能发生在下面的cs1998 .
public async Task<object> Foo()
{
return object;
}
然后你可以在下面改革 .
public async Task<object> Foo()
{
var result = await Task.Run(() =>
{
return object;
});
return result;
}
-1
如果您没有任何要等待的东西,请返回Task.FromResult
public Task<int> Success() // note: no "async"
{
... // Do not have await code
var result = ...;
return Task.FromResult(result);
}
3
根据您的方法签名,这里有一些替代方案 .
public async Task Test1()
{
await Task.CompletedTask;
}
public async Task<object> Test2()
{
return await Task.FromResult<object>(null);
}
public async Task<object> Test3()
{
return await Task.FromException<object>(new NotImplementedException());
}
public async Task<object> test()
{
//a pseudo code just to disable the warning about lack of await in async code!
var xyz = true ? 0 : await Task.FromResult(0); //use a var name that's not used later
//... your code statements as normal, eg:
//throw new NotImplementedException();
}
public abstract class TagHelper : ITagHelper, ITagHelperComponent
{
public virtual void Process(TagHelperContext context, TagHelperOutput output)
{
}
public virtual Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
Process(context, output);
return Task.CompletedTask; // *** this will avoid the lacks await warning!
}
}
3
// This is to get rid of warning CS1998, please remove when implementing this method.
await new Task(() => { }).ConfigureAwait(false);
throw new NotImplementedException();
8
您可以从方法中删除async关键字,然后让它返回Task;
public async Task DoTask()
{
State = TaskStates.InProgress;
await RunTimer();
}
public Task RunTimer()
{
return new Task(new Action(() =>
{
using (var t = new time.Timer(RequiredTime.Milliseconds))
{
t.Elapsed += ((x, y) => State = TaskStates.Completed);
t.Start();
}
}));
}
14 回答
方法返回
Task
,我相信 .async
是一个实现细节,因此无法应用于接口方法 .在这些情况下,您可以利用
async
是实现细节的事实 .如果你没有
await
,那么你可以返回Task.FromResult
:在抛出
NotImplementedException
的情况下,程序有点罗嗦:如果你有很多方法抛出
NotImplementedException
(它本身可能表明某些设计级重构会很好),那么你可以将wordiness包装成一个帮助类:辅助类还减少了GC本来必须收集的垃圾,因为具有相同返回类型的每个方法都可以共享其
Task
和NotImplementedException
对象 .我还有其他几个"task constant" type examples in my AsyncEx library .
另一种选择,如果你想保持函数的主体简单而不是编写代码来支持它,只需用#pragma来抑制警告:
如果这很常见,您可以将disable语句放在文件的顶部并省略还原 .
http://msdn.microsoft.com/en-us/library/441722ys(v=vs.110).aspx
另一种保留async关键字的方法(如果你想保留它)是使用:
填充方法后,您只需删除该语句即可 . 我经常使用它,特别是当一个方法可能等待某些东西但不是每个实现实际上都有 .
我知道这是一个旧线程,也许这对所有用法都没有正确的效果,但是当我还没有实现一个方法时,以下就能够简单地抛出一个NotImplementedException,不改变方法签名 . 如果它有问题,我会很高兴知道它,但它对我来说几乎不重要:我只是在开发过程中使用它,所以它的表现并不是那么重要 . 不过,我很高兴听到为什么这是一个坏主意,如果是的话 .
这是我为了实现这一目的而添加的类型 .
正如Stephen's Answer的更新一样,您不再需要编写
TaskConstants
类,因为有一个新的帮助方法:解决方案之间存在差异,严格来说,您应该知道调用方将如何调用异步方法,但使用默认使用模式假定".Wait()"方法结果 - “ return Task.CompletedTask ”是最佳解决方案 .
注意:
FromResult
无法直接比较 .测试代码:
}
如果您已经链接到Reactive Extension,您还可以执行以下操作:
Reactive和async / await既令人惊叹又独立,但它们也能很好地协同工作 .
包括需要的是:
它可能发生在下面的cs1998 .
然后你可以在下面改革 .
如果您没有任何要等待的东西,请返回Task.FromResult
根据您的方法签名,这里有一些替代方案 .
试试这个:
[System.Diagnostics.CodeAnalysis.SuppressMessage("Await.Warning", "CS1998:Await.Warning")]
见:https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.codeanalysis.suppressmessageattribute?view=netframework-4.7.2
首先,我发现了一个绕过这个警告的技巧:
这是一个伪代码,用于在asycn方法中禁用有关缺少
await
的警告!那个 await 关键字的存在会导致编译器欺骗不提出警告,即使我们知道它永远不会被调用!因为条件是true
它总是返回三元条件(?:)的第一部分,并且因为这个var是非使用var,它将在发布版本中省略 . 我不确定这种方法是否有任何副作用 .另外,我发现这个简单的方法在asp.net core(TagHelper.cs)的源代码中使用,但是需要从方法签名行中删除
async
关键字:return Task.CompletedTask;
这是更完整的代码:
您可以从方法中删除async关键字,然后让它返回Task;