Reputation: 2559
I've got an interface with some functions that return Task
. Some of the classes that implement the interface do not have anything to await, while others might just throw - so the warnings are spurious and annoying.
Is it possible to suppress these warnings? E.g.:
public async Task<object> test()
{
throw new NotImplementedException();
}
yields:
warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
Upvotes: 140
Views: 99720
Reputation: 831
Use throw of yielded exception
public async Task<object> DoSomethingAsync()
{
throw await Task.FromException<NotImplementedException>(new NotImplementedException());
}
Upvotes: -1
Reputation: 24395
Cleanest wait to suppress this warning is to just use await Task.CompletedTask;
before throwing. This functions as a no-op
public async Task SomeMethod()
{
await Task.CompletedTask;
throw new NotImplementedException();
}
Upvotes: -1
Reputation: 137
Configure/Suppress it globally:
in .editorconfig
# CS1998: Async method lacks 'await' operators and will run synchronously
dotnet_diagnostic.CS1998.severity = suggestion
In a common, not high performance, application the overhead of unneccessary async is negligible, and the benefits of brain-off async-all-the-way for regular coders is more important. (+ additional compiler checks etc.)
Upvotes: 7
Reputation: 1544
Just as an update to Stephen's Answer, you no longer need to write the TaskConstants
class as there is a new helper method:
public Task ThrowException()
{
try
{
throw new NotImplementedException();
}
catch (Exception e)
{
return Task.FromException(e);
}
}
Upvotes: 9
Reputation: 609
You might try this:
public async Task<object> test()
{
await Task.CompletedTask;
}
Upvotes: 9
Reputation: 9776
There is difference between solutions and strictly speaking you should know how caller is going to call the async method, but with default usage pattern that assumes ".Wait()" on method result - "return Task.CompletedTask" is the best solution.
BenchmarkDotNet=v0.10.11, OS=Windows 10 Redstone 3 [1709, Fall Creators Update] (10.0.16299.192)
Processor=Intel Core i5-2500K CPU 3.30GHz (Sandy Bridge), ProcessorCount=4
Frequency=3233537 Hz, Resolution=309.2589 ns, Timer=TSC
.NET Core SDK=2.1.2
[Host] : .NET Core 2.0.3 (Framework 4.6.25815.02), 64bit RyuJIT
Clr : .NET Framework 4.7 (CLR 4.0.30319.42000), 64bit RyuJIT-v4.7.2600.0
Core : .NET Core 2.0.3 (Framework 4.6.25815.02), 64bit RyuJIT
Method | Job | Runtime | Mean | Error | StdDev | Median | Min | Max | Rank | Gen 0 | Gen 1 | Gen 2 | Allocated |
--------------- |----- |-------- |-------------:|------------:|------------:|-------------:|-------------:|-------------:|-----:|-------:|-------:|-------:|----------:|
CompletedAwait | Clr | Clr | 95.253 ns | 0.7491 ns | 0.6641 ns | 95.100 ns | 94.461 ns | 96.557 ns | 7 | 0.0075 | - | - | 24 B |
Completed | Clr | Clr | 12.036 ns | 0.0659 ns | 0.0617 ns | 12.026 ns | 11.931 ns | 12.154 ns | 2 | 0.0076 | - | - | 24 B |
Pragma | Clr | Clr | 87.868 ns | 0.3923 ns | 0.3670 ns | 87.789 ns | 87.336 ns | 88.683 ns | 6 | 0.0075 | - | - | 24 B |
FromResult | Clr | Clr | 107.009 ns | 0.6671 ns | 0.6240 ns | 107.009 ns | 106.204 ns | 108.247 ns | 8 | 0.0584 | - | - | 184 B |
Yield | Clr | Clr | 1,766.843 ns | 26.5216 ns | 24.8083 ns | 1,770.383 ns | 1,705.386 ns | 1,800.653 ns | 9 | 0.0877 | 0.0038 | 0.0019 | 320 B |
CompletedAwait | Core | Core | 37.201 ns | 0.1961 ns | 0.1739 ns | 37.227 ns | 36.970 ns | 37.559 ns | 4 | 0.0076 | - | - | 24 B |
Completed | Core | Core | 9.017 ns | 0.0690 ns | 0.0577 ns | 9.010 ns | 8.925 ns | 9.128 ns | 1 | 0.0076 | - | - | 24 B |
Pragma | Core | Core | 34.118 ns | 0.4576 ns | 0.4281 ns | 34.259 ns | 33.437 ns | 34.792 ns | 3 | 0.0076 | - | - | 24 B |
FromResult | Core | Core | 46.953 ns | 1.2728 ns | 1.1905 ns | 46.467 ns | 45.674 ns | 49.868 ns | 5 | 0.0533 | - | - | 168 B |
Yield | Core | Core | 2,480.980 ns | 199.4416 ns | 575.4347 ns | 2,291.978 ns | 1,810.644 ns | 4,085.196 ns | 10 | 0.0916 | - | - | 296 B |
Note: FromResult
can't be directly compared.
Test Code:
[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);
}
}
}
Upvotes: 23
Reputation: 1601
Try this:
[System.Diagnostics.CodeAnalysis.SuppressMessage("Await.Warning", "CS1998:Await.Warning")]
Upvotes: 2
Reputation: 537
Here is some alternatives depending on your method signature.
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());
}
Upvotes: 0
Reputation: 159
If you don't have anything to await then return Task.FromResult
public Task<int> Success() // note: no "async"
{
... // Do not have await code
var result = ...;
return Task.FromResult(result);
}
Upvotes: 0
Reputation: 1
You can drop the async keyword from the method and just have it return 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();
}
}));
}
Upvotes: -4
Reputation: 28
// This is to get rid of warning CS1998, please remove when implementing this method.
await new Task(() => { }).ConfigureAwait(false);
throw new NotImplementedException();
Upvotes: -3
Reputation: 105
It might be occured cs1998 below.
public async Task<object> Foo()
{
return object;
}
Then you can reform below.
public async Task<object> Foo()
{
var result = await Task.Run(() =>
{
return object;
});
return result;
}
Upvotes: 0
Reputation: 893
I know this is an old thread, and perhaps this won't have the right effect for all usages, but the following is as close as I can get to being able to simply throw a NotImplementedException when I haven't yet implemented a method, without altering the method signature. If it's problematic I'd be happy to know about it, but it barely matters to me: I only use this while in development anyway, so how it performs isn't all that important. Still, I'd be happy to hear about why it's a bad idea, if it is.
public async Task<object> test()
{
throw await new AwaitableNotImplementedException<object>();
}
Here's the type I added to make that possible.
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;
}
}
Upvotes: 10
Reputation: 5234
Another way to preserve the async keyword (in case you want to keep it) is to use:
public async Task StartAsync()
{
await Task.Yield();
}
Once you populate the method you can simply remove the statement. I use this a lot especially when a method might await something but not every implementation actually does.
Upvotes: 48
Reputation: 7049
In case you already link against Reactive Extension, you can also do:
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 and async/await are both amazing in and by themselves, but they also play well together.
Includes needed are:
using System.Reactive.Linq;
using System.Reactive.Threading.Tasks;
Upvotes: 3
Reputation: 456537
I've got an interface with some async functions.
Methods returning Task
, I believe. async
is an implementation detail, so it can't be applied to interface methods.
Some of the classes that implements the interface does not have anything to await, and some might just throw.
In these cases, you can take advantage of the fact that async
is an implementation detail.
If you have nothing to await
, then you can just return Task.FromResult
:
public Task<int> Success() // note: no "async"
{
... // non-awaiting code
int result = ...;
return Task.FromResult(result);
}
In the case of throwing NotImplementedException
, the procedure is a bit more wordy:
public Task<int> Fail() // note: no "async"
{
var tcs = new TaskCompletionSource<int>();
tcs.SetException(new NotImplementedException());
return tcs.Task;
}
If you have a lot of methods throwing NotImplementedException
(which itself may indicate that some design-level refactoring would be good), then you could wrap up the wordiness into a helper class:
public static class TaskConstants<TResult>
{
static TaskConstants()
{
var tcs = new TaskCompletionSource<TResult>();
tcs.SetException(new NotImplementedException());
NotImplemented = tcs.Task;
}
public static Task<TResult> NotImplemented { get; private set; }
}
public Task<int> Fail() // note: no "async"
{
return TaskConstants<int>.NotImplemented;
}
The helper class also reduces garbage that the GC would otherwise have to collect, since each method with the same return type can share its Task
and NotImplementedException
objects.
I have several other "task constant" type examples in my AsyncEx library.
Upvotes: 144
Reputation: 1187
Another option, if you want to keep the body of the function simple and not write code to support it, is simply to suppress the warning with #pragma:
#pragma warning disable 1998
public async Task<object> Test()
{
throw new NotImplementedException();
}
#pragma warning restore 1998
If this is common enough, you could put the disable statement at the top of the file and omit the restore.
http://msdn.microsoft.com/en-us/library/441722ys(v=vs.110).aspx
Upvotes: 85