If My Interface Must Return Task How to Have a No-Operation Implementation

If my interface must return Task what is the best way to have a no-operation implementation?

Today, I would recommend using Task.CompletedTask to accomplish this.


Pre .net 4.6:

Using Task.FromResult(0) or Task.FromResult<object>(null) will incur less overhead than creating a Task with a no-op expression. When creating a Task with a result pre-determined, there is no scheduling overhead involved.

Should all interfaces be re-written to return TaskResult?

This design issue is parallel with IDisposable. When you are writing an interface, you have to know whether it's "likely" that derived types will need IDisposable, and derive from it if they will. Non-disposable types like test stubs just implement a noop Dispose.

Similarly, when you are writing an interface, you have to know whether it's "likely" that derived types will use asynchronous implementations.

Note that the question for derived types is: "Will the implementation be naturally asynchronous?", not "Will the implementation be fast?". Speed has nothing to do with it. The only thing you should consider is whether the implementations may be naturally-asynchronous (i.e., using I/O or other asynchronous methods).

When you write an interface, there's usually one (or a small number) of implementations that you have in mind; I recommend that you just consider those when deciding to make the interface methods asynchronous. You could go extreme and just make every interface method asynchronous, but that would be like using IDisposable everywhere - not a pattern that I'd recommend.

So, I would say that if your (current) implementations are all synchronous for a particular method, then make that method synchronous; otherwise, make it asynchronous.

As you noted, an asynchronous method signature technically means that the implementation may be asynchronous. Test stubs and the like can use Task.FromResult to implement an asynchronous signature synchronously. Personally, I think this is perfectly acceptable for stub implementations; but I would not recommend making a method async "just in case", when all current implementations are synchronous.

Also, I'm strongly against having both signatures. This would require implementors to wrap sync-over-async or async-over-sync, neither of which is ideal.

Is it better to return an empty task or null? c#

if it finds no results is it better to return an empty task or null?

There's a couple things to consider here:

First, you should never return a null Task. In the async world, a null task just doesn't make sense. Task represents the execution of the asynchronous method, so for an asynchronous method to return a null task is like telling the calling code "you didn't really just call this method" when of course it did.

So, a Task/Task<T> returned from a method should never, ever be null. However, you still have the option of returning a null value inside a regular task. That is up to you.

with tasks i am unsure which is best.

The task is just a wrapper. The underlying logic is still the same. Think of how this method would look if it were synchronous; would your return type be int and return 0 if nothing was found, or would your return type be int? and return null if nothing was found? After making that choice for a synchronous method, then wrap it in Task<T> for the asynchronous method.

As a final note, I must say:

  • Do not ever, ever use the Task constructor.
  • Avoid Task<T>.Result; use await instead.
  • Do not use ContinueWith; use await instead.

Your method can be drastically simplified:

public virtual async Task<int> GetJobRunIdAsync(int jobId)
{
var jobMonRequest = ...;
var jobMonResponse = await Client.jobmonAsync(jobMonRequest);
if (jobMonResponse == null)
return 0;
if (jobMonResponse.jobrun.Length > 1)
throw new Exception("More than one job found, Wizards are abound.");
return jobMonResponse.jobrun.Single().id;
}

Or, if you want to return a value (not task) of null:

public virtual async Task<int?> GetJobRunIdAsync(int jobId)
{
var jobMonRequest = ...;
var jobMonResponse = await Client.jobmonAsync(jobMonRequest);
if (jobMonResponse == null)
return null;
if (jobMonResponse.jobrun.Length > 1)
throw new Exception("More than one job found, Wizards are abound.");
return jobMonResponse.jobrun.Single().id;
}

How to implement interface method that returns TaskT?

When you have to implement an async method from an interface and your implementation is synchronous, you can either use Ned's solution:

public Task<Bar> CreateBarAsync()
{
return Task.FromResult<Bar>(SynchronousBarCreator());
}

With this solution, the method looks async but is synchronous.

Or the solution you proposed:

  Task<Bar> CreateBarAsync()
{
return Task.Run(() => SynchronousBarCreator());
}

This way the method is truly async.

You don't have a generic solution that will match all cases of "How to implement interface method that returns Task". It depends on the context: is your implementation fast enough so invoking it on another thread is useless? How is this interface used a when is this method invoked (will it freeze the app)? Is it even possible to invoke your implementation in another thread?

How do you handle a 3rd party interface returning Task if you don't have any async code?

If you don't have async work to do don't include the async keyword. Your GetValueAsnyc function was almost correct, you just needed to drop the async. For your DoWorkAsync you should just not mark the method async and return a completed task.

public class FooBar : IFoo
{
public Task DoWorkAsync()
{
// Do Some Work

//If you can use .NET 4.6
return Task.CompletedTask;

//For older versions, the thing you pass in does not matter, I like to use bool.
return Task.FromResult(false);
}

public Task<int> GetValueAsync()
{
// Do Some Work
var result = ...;

return Task.FromResult(result);
}
}

However, if your code is slow and you end up blocking the UI for a long period of time I would consider looking in to if you can re-write your code as actually being async or perhaps wrapping the code in to a background thread, but I would only do a background thread if it was a last resort.

Implementing an interface that requires a Task return type in synchronous code

Yes: now there's Task.CompletedTask as of .NET 4.6.

Is returning Task.FromResultvalue when doing synchronous work to satisfy interface bad?

Is this considered the right approach for situations like this?

I would say No, for rather subtle reasons.

Task.FromResult allows you to return a task from a non-async method, sure. And it works fine for the successful case. But it doesn't work as expected for the exceptional case.

Methods with an asynchronous signature are expected to place all the method results on the returned task. They can complete synchronously - there's nothing wrong with that - but any exception is considered a "result" in this sense and should be placed on the returned task.

So, you'd want to catch any exceptions from ExecuteSyncCode (or even new TaskResult()) and return Task.FromException if there was one. And then to be properly pedantic, you may also want to catch OperationCanceledException explicitly and return Task.FromCanceled. By the time you're done handling all the corner cases, your code ends up looking something like this.

And by that time, your "simple" synchronous implementation is full of a bunch of boilerplate that muddles up the code and confuses future maintainers.

For this reason, I tend to prefer just marking the method as async and not using await. This will cause a compiler warning (CS1998 This async method lacks 'await' operators and will run synchronously.), which is generally useful but which you can #pragma ignore for this specific case since you want a synchronous implementation. Using async essentially makes the compiler do all that boilerplate for you, while keeping the implementation synchronous.

If you end up with several synchronous implementations of asynchronous interfaces, I'd recommend defining a couple static helper methods like this. That way, the ugly #pragmas are confined to a single helper class.

Interface Requiring Function That Returns Task

You could Return Task.CompletedTask. This is useful in cases like the one you describe where you need to satisfy an interface method that returns a Task, but you have nothing to await in your concrete implementation.

Public Function MoveToNextField() As Task Implements FormObjects.Interfaces.IViewer.MoveToNextField
Return Task.CompletedTask
End Function


Related Topics



Leave a reply



Submit