Correct way to expose a cancellable Task API - c#

If I want to expose an API which internally Schedules a sequence of Tasks that should be cancellable by the user.
e.g.
public ??? DoWork()
{
Task t = new .... , myCancellationToken);
return ???
}
What is the correct object to return for cancellation Control?
Is it CancellationTokenSource ?
public CancellationTokenSource DoWork()
{
CancellationTokenSource source = new ....
Task t = new .... , source.Token);
return source;
}
Should I return anything at all?
Should I just accept a CancellationToken as an arg and let the user create the token source if needed?
public void DoWork(CancellationToken token)
{
Task t = new .... , token);
}
What is the most idiomatic way to deal with this?

Should I just accept a CancellationToken as an arg and let the user create the token source if needed?
This. But you should quite possibly return a Task as well, so that the user can observe when it's completed etc. This is amenable to async/await as well, of course.
You may also want to have overloads:
public Task DoWork()
{
return DoWork(CancellationToken.None);
}
public Task DoWork(CancellationToken cancellationToken)
{
...
}
See the Task-based Asynchronous Pattern for general conventions on this sort of thing.

Async methods should return the Task. You will need the Task for syncronization purpose as well as for getting the result if you do not implement callback-Patterns with IAsync. If you mark the method with async and call it with await the result is unwrapped from the Task automatically.
Task is the point of interest in TPL. Do not create a new Task if you do not need to do it explicitle, prefer the static Run method instead.

Related

How to convert a YieldAwaitable to a Task [duplicate]

In contrast to Task.Wait() or Task.Result, await’ing a Task in C# 5 prevents the thread which executes the wait from lying fallow. Instead, the method using the await keyword needs to be async so that the call of await just makes the method to return a new task which represents the execution of the async method.
But when the await’ed Task completes before the async method has received CPU time again, the await recognizes the Task as finished and thus the async method will return the Task object only at a later time. In some cases this would be later than acceptable because it probably is a common mistake that a developer assumes the await’ing always defers the subsequent statements in his async method.
The mistaken async method’s structure could look like the following:
async Task doSthAsync()
{
var a = await getSthAsync();
// perform a long operation
}
Then sometimes doSthAsync() will return the Task only after a long time.
I know it should rather be written like this:
async Task doSthAsync()
{
var a = await getSthAsync();
await Task.Run(() =>
{
// perform a long operation
};
}
... or that:
async Task doSthAsync()
{
var a = await getSthAsync();
await Task.Yield();
// perform a long operation
}
But I do not find the last two patterns pretty and want to prevent the mistake to occur. I am developing a framework which provides getSthAsync and the first structure shall be common. So getSthAsync should return an Awaitable which always yields like the YieldAwaitable returned by Task.Yield() does.
Unfortunately most features provided by the Task Parallel Library like Task.WhenAll(IEnumerable<Task> tasks) only operate on Tasks so the result of getSthAsync should be a Task.
So is it possible to return a Task which always yields?
First of all, the consumer of an async method shouldn't assume it will "yield" as that's nothing to do with it being async. If the consumer needs to make sure there's an offload to another thread they should use Task.Run to enforce that.
Second of all, I don't see how using Task.Run, or Task.Yield is problematic as it's used inside an async method which returns a Task and not a YieldAwaitable.
If you want to create a Task that behaves like YieldAwaitable you can just use Task.Yield inside an async method:
async Task Yield()
{
await Task.Yield();
}
Edit:
As was mentioned in the comments, this has a race condition where it may not always yield. This race condition is inherent with how Task and TaskAwaiter are implemented. To avoid that you can create your own Task and TaskAwaiter:
public class YieldTask : Task
{
public YieldTask() : base(() => {})
{
Start(TaskScheduler.Default);
}
public new TaskAwaiterWrapper GetAwaiter() => new TaskAwaiterWrapper(base.GetAwaiter());
}
public struct TaskAwaiterWrapper : INotifyCompletion
{
private TaskAwaiter _taskAwaiter;
public TaskAwaiterWrapper(TaskAwaiter taskAwaiter)
{
_taskAwaiter = taskAwaiter;
}
public bool IsCompleted => false;
public void OnCompleted(Action continuation) => _taskAwaiter.OnCompleted(continuation);
public void GetResult() => _taskAwaiter.GetResult();
}
This will create a task that always yields because IsCompleted always returns false. It can be used like this:
public static readonly YieldTask YieldTask = new YieldTask();
private static async Task MainAsync()
{
await YieldTask;
// something
}
Note: I highly discourage anyone from actually doing this kind of thing.
Here is a polished version of i3arnon's YieldTask:
public class YieldTask : Task
{
public YieldTask() : base(() => { },
TaskCreationOptions.RunContinuationsAsynchronously)
=> RunSynchronously();
public new YieldAwaitable.YieldAwaiter GetAwaiter()
=> default;
public new YieldAwaitable ConfigureAwait(bool continueOnCapturedContext)
{
if (!continueOnCapturedContext) throw new NotSupportedException();
return default;
}
}
The YieldTask is immediately completed upon creation, but its awaiter says otherwise. The GetAwaiter().IsCompleted always returns false. This mischief makes the await operator to trigger the desirable asynchronous switch, every time it awaits this task. Actually creating multiple YieldTask instances is redundant. A singleton would work just as well.
There is a problem with this approach though. The underlying methods of the Task class are not virtual, and hiding them with the new modifier means that polymorphism doesn't work. If you store a YieldTask instance to a Task variable, you'll get the default task behavior. This is a considerable drawback for my use case, but I can't see any solution around it.

Task.Wait doesn't wait for async method completion

Here is the code:
static async Task Main(string[] args)
{
var t = new Task(async () => await AsyncTest());
t.Start();
t.Wait();
Console.WriteLine("Main finished");
}
private static async Task AsyncTest()
{
Thread.Sleep(2000);
await Task.Delay(2000);
Console.WriteLine("Method finished");
}
My expectation is that t.Wait() will actually wait for AsyncTest method completion and output will be:
Method finished
Main finished
In reality output has only Main finished. Wait() is completed right at the moment when you hit await Task.Delay(2000) inside AsyncTest. The same happens if you replace t.Wait() with await t / await Task.WhenAll(t) / Task.WaitAll(t).
The solution is to rewrite method to synchronous implementation or call Wait() directly on AsyncTest(). However, the question is why does it work in such strange way?
P.S. It's a simplified version of code. I was trying to achieve deferred task execution. In reality Task object is created by one part of program and then later is executed by another part after some specific condition.
UPD: Rewriting var t = new Task(async () => await AsyncTest()) to var t = new Task(()=> AsyncTest().Wait()) also fixes the problem. Though I still don't quite understand why Task doesn't work correctly with async/await inside delegate.
I still don't quite understand why Task doesn't work correctly with async/await inside delegate.
Because the Task constructor is only used for creating Delegate Tasks - i.e., tasks that represent synchronous code to be run. Since the code is synchronous, your async lambda is being treated as an async void lambda, which means the Task instance won't asynchronously wait for AsyncTest to complete.
More to the point, the Task constructor should never, ever be used in any code, anywhere, for any reason. It has literally zero valid use cases.
A good replacement for Task.Task is Task.Run, which does understand async lambdas.
In my real program Task has deferred execution. Task object is created in one place, and then later after specific condition executed by another part of program.
In that case, use an asynchronous delegate. Specifically, Func<Task>.
static async Task Main(string[] args)
{
Func<Task> func = AsyncTest;
// Later, when we're ready to run.
await func();
Console.WriteLine("Main finished");
}
private static async Task AsyncTest()
{
Thread.Sleep(2000);
await Task.Delay(2000);
Console.WriteLine("Method finished");
}
A quote from #JonSkeet:
Your async method just returns void, which means there's no simple way
of anything waiting for it to complete. (You should almost always
avoid using async void methods. They're really only available for the
sake of subscribing to events.)
So look at this line of your code:
var t = new Task(async () => await AsyncTest());
Look at the signature of Task constructors:
public Task(Action action);
public Task(Action action, CancellationToken cancellationToken);
public Task(Action action, TaskCreationOptions creationOptions);
public Task(Action<object> action, object state);
public Task(Action action, CancellationToken cancellationToken, TaskCreationOptions creationOptions);
public Task(Action<object> action, object state, CancellationToken cancellationToken);
public Task(Action<object> action, object state, TaskCreationOptions creationOptions);
public Task(Action<object> action, object state, CancellationToken cancellationToken, TaskCreationOptions creationOptions);
All of them are Actions and as you know Action has void return type.
static async Task Main(string[] args)
{
// best way to do it
await AsyncTest();
Console.WriteLine("Main finished");
}
private static async Task AsyncTest()
{
// Don't use thread sleep, await task delay is fine
// Thread.Sleep(2000);
await Task.Delay(2000);
Console.WriteLine("Method finished");
}
check this
public static async Task Main(string[] args)
{
var t = Task.Factory.StartNew(async () => await AsyncTest());
//t.Start();
t.Result.Wait();
t.Wait();
Console.WriteLine("Main finished");
}
private static async Task AsyncTest()
{
//Thread.Sleep(2000);
await Task.Delay(2000);
Console.WriteLine("Method finished");
}
and this link
Don't use var task = new Task(...); task.Start();, use just Task.Run instead.
In 1st case constructor Task(Action action) is used so you actually doesn't await async method actually. If you inspect real C# without asyn-await syntax sugar you will see AsyncVoidMethodBuilder. In case of Task.Run you use Task.Run(Func<Task> func) so you receive "real" tasks.
So if you want to use constructor you should use approach from comments: new Task<Task>.

TPL-based looping service: right worker method signature, asynchrony

Regarding the right worker method signature I need to understand the following:
is there a point in returning Task instead of void for Worker method (if going sync)?
Should I really wait (call Wait()) on the Worker method (if going sync)?
what should be the return value of Worker method when marked as returning Task object (both if going sync/async)?
what signature and body of Worker method should be, given the work it completes is long-running CPU/IO-bound work? Should I follow this recommendation (if going mixed/async)?
Note
Despite the cpu-bound code, there's a choice to call async versions of io-bound methods (sql queries). So it may be all sync or partially async. As for the nature of code in the Worker method.
public class LoopingService
{
private CancellationTokenSource cts;
// ..
void Worker(CancellationToken cancellationToken)
{
while(!cancellationToken.IsCancellationRequested)
{
// mixed, CPU/IO-bound code
try {
// sql query (can be called either as sync/async)
var lastId = documentService.GetLastDocument().Id;
// get next document from a public resource (third-party code, sync)
// can be moved to a web api
var document = thirdPartyDocumentService.GetNextDocument(lastId);
// apply different processors in parallel
var tasksList = new List<Task>();
foreach(var processor in documentService.Processors) {
// each processor checks if it's applicable
// which may include xml-parsing, additional db calls, regexes
// if it's applicable then document data is inserted into the db
var task = new Task(() => processor.Process(document));
tasksList.Add(task);
task.Start();
}
// or
// var tasksList = documentService.ProcessParallel(document);
Task.WaitAll(tasksList.ToArray(), cancellationToken);
}
catch(Exception ex) {
logger.log(ex);
}
}
}
public void Start()
{
this.cts = new CancellationTokenSource();
Task.Run(() => this.Worker(cts.Token));
}
public void Stop()
{
this.cts.Cancel();
this.cts.Dispose();
}
}
is there a point in returning Task instead of void for Worker method?
If Worker is a truly asynchronous method it should return a Task for you to be able to await it. If it's just a synchronous method runnning on a background thread there is no point of changing the return type from void provided that the method is not supposed to return anything.
what should be the return value of Worker method when marked as returning Task object?
Nothing. Provided that the method is asynchronous and marked as async with a return type of Task, it shouldn't return any value:
async Task Worker(CancellationToken cancellationToken) { ... }
Note that there is no point of defining the method as async unless you actually use the await keyword in it.
what signature and body of Worker method should be given the work it completes is long-running CPU/IO-bound work? Should I follow this recommendation?
Yes, probably. If you for some reason are doing both asynchronous and synchronous (CPU-bound) work in the same method, you should prefer to using an asynchronous signature but not wrap the synchronous stuff in Task.Run. Then your service would look something like this:
public class LoopingService
{
private CancellationTokenSource cts;
async Task Worker(CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
await ...
}
}
public async Task Start()
{
this.cts = new CancellationTokenSource();
await this.Worker(cts.Token).ConfigureAwait(false);
}
public void Stop()
{
this.cts.Cancel();
this.cts.Dispose();
}
}
Ideally your method should be either asynchronous or CPU-bound but not both though.

What is the use for Task.FromResult<TResult> in C#

In C# and TPL (Task Parallel Library), the Task class represents an ongoing work that produces a value of type T.
I'd like to know what is the need for the Task.FromResult method ?
That is: In a scenario where you already have the produced value at hand, what is the need to wrap it back into a Task?
The only thing that comes to mind is that it's used as some adapter for other methods accepting a Task instance.
There are two common use cases I've found:
When you're implementing an interface that allows asynchronous callers, but your implementation is synchronous.
When you're stubbing/mocking asynchronous code for testing.
One example would be a method that makes use of a cache. If the result is already computed, you can return a completed task with the value (using Task.FromResult). If it is not, then you go ahead and return a task representing ongoing work.
Cache Example: Cache Example using Task.FromResult for Pre-computed values
Use it when you want to create an awaitable method without using the async keyword.
I found this example:
public class TextResult : IHttpActionResult
{
string _value;
HttpRequestMessage _request;
public TextResult(string value, HttpRequestMessage request)
{
_value = value;
_request = request;
}
public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
var response = new HttpResponseMessage()
{
Content = new StringContent(_value),
RequestMessage = _request
};
return Task.FromResult(response);
}
}
Here you are creating your own implementation of the IHttpActionResult interface to be used in a Web Api Action. The ExecuteAsync method is expected to be asynchronous but you don't have to use the async keyword to make it asynchronous and awaitable. Since you already have the result and don't need to await anything it's better to use Task.FromResult.
From msft.com Create pre-computed tasks with Task.FromResult:
This method is useful when you perform an asynchronous operation that returns a Task object, and the result of that Task object is already computed.
Use the Task.FromResult when you want to have a asynchronous operation but sometimes the result is in hand synchronously. You can find a good sample here http://msdn.microsoft.com/en-us/library/hh228607.aspx.
I would argue that you could use Task.FromResult for methods that are synchronous that take a long time to complete while you can do other independent work in your code. Id rather make those methods to call async though. But imagine the situation where you have no control over the code called and you want that implicit parallel processing.
Task.Run() creates an lambda thread, no async is required and returns a type object. In my example, I have multiple tasks running simulatenously awaiting their completion. Once all the tasks have completed, I can cycle through their results. Task.FromResult is used to push a task result not generated by Task.Run()
The Task.FromResult pushs a type object in this case RecordStruct class in Result class. I created to tasks calling the function getData. The Task.WaitAll processes each of the task and push the results into an array of result object of type RecordStruct. I then access the attribute element of the RecordStruct Class as a result
public class RecordStruct
{
public RecordStruct(string _element) {
element = _element;
}
public string element { get;set; }
}
public class TaskCustom
{
public Task<RecordStruct> getData(string phrase)
{
if (phrase == "hello boise")
{
return Task.FromResult(new RecordStruct("Boise is a great place to live"));
}
return Task.Run(() =>
{
return new RecordStruct(phrase);
});
}
}
[Fact]
public async Task TestFactory()
{
TaskCustom obj = new TaskCustom();
List<Task<RecordStruct>> tasks = new List<Task<RecordStruct>>();
tasks.Add(obj.getData("hello world"));
tasks.Add(obj.getData("hello boise"));
Task.WaitAll(tasks.ToArray());
for(int ctr = 0; ctr < tasks.Count; ctr++) {
if (tasks[ctr].Status == TaskStatus.Faulted)
output.WriteLine(" Task fault occurred");
else
{
output.WriteLine("test sent {0}",
tasks[ctr].Result.element);
Assert.True(true);
}
}
}

Converting an async method to return IObservable<>

I have an async method that is a long-running method that reads a stream and when it finds something fires an event:
public static async void GetStream(int id, CancellationToken token)
It takes a cancellation token because it is create in a new task. Internally it calls await when it reads a stream:
var result = await sr.ReadLineAsync()
Now, I want to convert this to a method that returns an IObservable<> so that I can use this with the reactive extensions. From what I've read, the best way to do this is using Observable.Create, and since RX 2.0 now also supports async I can get it all to work with something like this:
public static IObservable<Message> ObservableStream(int id, CancellationToken token)
{
return Observable.Create<Message>(
async (IObserver<Message> observer) =>
{
The rest of the code inside is the same, but instead of firing events I'm calling observer.OnNext(). But, this feels wrong. For one thing I'm mixing CancellationTokens up in there, and although adding the async keyword made it work, is this actually the best thing to do? I'm calling my ObservableStream like this:
Client.ObservableStream(555404, token).ObserveOn(Dispatcher.CurrentDispatcher).SubscribeOn(TaskPoolScheduler.Default).Subscribe(m => Messages.Add(m));
You are correct. Once you represent your interface through an IObservable, you should avoid requiring the callers to supply a CancellationToken. That doesn't mean you cannot use them internally. Rx provides several mechanisms to produce CancellationToken instances which are canceled when the observer unsubscribes from your observable.
There are a number of ways to tackle your problem. The simplest requires almost no changes in your code. It uses an overload of Observable.Create which supplies you with a CancellationToken that triggers if the caller unsubscribes:
public static IObservable<Message> ObservableStream(int id)
{
return Observable.Create<Message>(async (observer, token) =>
{
// no exception handling required. If this method throws,
// Rx will catch it and call observer.OnError() for us.
using (var stream = /*...open your stream...*/)
{
string msg;
while ((msg = await stream.ReadLineAsync()) != null)
{
if (token.IsCancellationRequested) { return; }
observer.OnNext(msg);
}
observer.OnCompleted();
}
});
}
You should change GetStream to return a Task, instead of void (returning async void is not good, except when absolutely required, as svick commented). Once you return a Task, you can just call .ToObservable() and you are done.
For example:
public static async Task<int> GetStream(int id, CancellationToken token) { ... }
Then,
GetStream(1, new CancellationToken(false))
.ToObservable()
.Subscribe(Console.Write);

Categories

Resources