execute aync methods in order - c#

I have:
public myclass
{
public async Task method1();
public async Task method2();
public async Task method3();
}
I implement a function which should execute on myclass object these 3 mthods one after another. I am not sure which way is better (performance/correctness):
1)
public async Task mymethod(myclass obj)
{
await obj.method1();
await obj.method2();
await obj.method3();
}
myclass myobj = new myclass();
await myobj.method(myobj);
2)
public Task mymethod(myclass obj)
{
obj.method1();
obj.method2();
obj.method3();
}
myclass myobj = new myclass();
await myobj.method(myobj);

Only the first example is correct.
Even if you fixed the second example so that it returned a Task object, you still would have the problem that each individual method would be operating concurrently with the other two, which seems to be exactly what you don't want. I.e. in the second example, you don't wait for one method to finish before calling the next.
Since you would have to add some kind of waiting to the second example anyway, just to get it to work correctly, you should just go ahead and use the correct, idiomatic async/await technique seen in your first example.

Related

Is there any way to know if a method is running being awaited from within the method?

I'm a university student but, since I like programming, I try to create a library of code that's been useful to me (something like a code base).
In the process of doing this, I started designing/writing an asynchronous method that's about to be used for interlocking a variable. My goal is to produce different result when this method is being awaited (runs synchronously) and when it isn't.
An example could be the following:
private int _lock;
public async Task<bool> Lock()
{
if (method_is_not_being_awaited)
return Interlocked.Exchange(ref _lock, 1) == 0;
while (0 != Interlocked.Exchange(ref _lock, 1)) {}
return true;
}
Is there any way to achieve such result? If yes, how?
ps: I know that I could make 2 different methods bool lock() and async Task<bool> lockAsync() but, that's not what I ask for
No, it is not possible to do what you want because method must return value before any operation on result (including await) can be performed. It is not specific to async methods but rather how all code behaves in C# (and pretty much any other language).
On other hand it is pretty easy to do something that very close to what you ask - synchronously return value as soon as one tries to await the result of the method: await is essentially just call to GetAwaiter on the result and you can wire it up to alter state of your method.
Note that you can't really know what to do if method ever awaited anyway - so while you can act at moment when await is called you really can't know in advance if you should start asynchronous processing. So the best you can achieve is to do nothing in synchronous part, start asynchronous processing anyway and instantly return result when await is called (aborting/ignoring asynchronous part of the method).
Details on implementing class that can be used as result can be found in https://www.codeproject.com/Articles/5274659/How-to-Use-the-Csharp-Await-Keyword-On-Anything and https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/task-asynchronous-programming-model.
Skeleton code below shows how to implement method that does nothing unless await is called:
class MyTask
{
public MyAwaitable GetAwaiter()
{
return new MyAwaitable();
}
}
class MyAwaitable : INotifyCompletion
{
public bool IsCompleted
{
get { return true; }
}
public int GetResult()
{
return 42; // this is our "result" from method.
}
public void OnCompleted (Action continuation)
{
// just run instantly - no need to save callback as this one is
// always "completed"
continuation();
}
}
MyTask F()
{
// if your really want you can start async operation here
// and somehow wire up MyAwaitable.IsComplete to terminate/abandon
// asynchronous part.
return new MyTask();
}

Does calling .Result on a task that has already been awaited break the async pattern?

By the time the code calls Task.Result, it has already been awaited, so does the asynchronous pattern here still hold?
class Program
{
static async Task Main(string[] args)
{
var addNumbersTask = AddNumbers(10, 20);
var result = AwaitForResult(addNumbersTask).Result;
Console.WriteLine(result);
}
static async Task<int> AddNumbers(int a, int b)
{
await Task.Delay(250);
return a + b;
}
static async Task<int> AwaitForResult(Task<int> task)
{
await task;
return task.Result;
}
}
Background if you're interested: Trying to emit IL code for a proxy class that needs to handle async calls, but I don't want to generate the async state machine in the IL. So I figured I could delegate the actual "await" part to a helper outside of the IL. Also, I know there are proxy types out there but the hopeless engineer in me wants to write it myself.
Edit: Updated example.
interface IService
{
Task<int> AddAsync(int a, int b);
}
class Service : IService
{
public async Task<int> AddAsync(int a, int b)
{
await Task.Delay(250); // Some web service call...
return a + b;
}
}
// This class 100% generated via reflection emit
class Proxy : IService
{
private readonly IService _actual;
public Proxy(IService actual) => _actual = actual;
public Task<int> AddAsync(int a, int b)
{
return Awaiter.Await(_actual.AddAsync(a, b));
}
}
static class Awaiter
{
public static async Task<int> Await(Task<int> task)
{
return await task;
}
}
class Program
{
static async Task Main(string[] args)
{
var proxy = new Proxy(new Service());
var result = await proxy.AddAsync(5, 5);
Console.WriteLine($"Result is {result}", result);
}
}
does the asynchronous pattern here still hold?
No. There's nothing magical about using await on a task. Instead, consider whether the task is completed. Calling task.Result will block the calling thread until task completes. Doing await task will asynchronously wait until task completes.
So in this code, Result will not block:
static async Task<int> AwaitForResult(Task<int> task)
{
// Task may not yet be complete here.
await task;
// At this point, task is complete.
// Since task is complete, Result does not block.
return task.Result;
}
But that is totally different than this code:
var result = AwaitForResult(addNumbersTask).Result;
// Equivalent to:
var task = AwaitForResult(addNumbersTask);
var result = task.Result;
The task returned from AwaitForResult may not be complete here, since it was never awaited. And if it's not complete, then Result will block.
Trying to emit IL code for a proxy class that needs to handle async calls, but I don't want to generate the async state machine in the IL. So I figured I could delegate the actual "await" part to a helper outside of the IL.
Have you tried Roslyn APIs? I find them much more convenient than IL emit.
If your proxy is just a pass-through, then you can just return the inner task directly:
// This class 100% generated via reflection emit
class Proxy : IService
{
private readonly IService _actual;
public Proxy(IService actual) => _actual = actual;
public Task<int> AddAsync(int a, int b) => _actual.AddAsync(a, b);
}
But if you want to add much real logic, then I'd recommend using Roslyn to generate the async state machine for you.
If you’re trying to avoid blocking, then no.
In your console app example it makes little difference, but if you did that somewhere where you don’t want blocking - e.g. a UI event handler - .Result will still block.
By the time you have a value in addNumbersTask, that task is started. You then immediately pass the task to AwaitForResult, which immediately begins to await it, at which point an incomplete task that returns an int is returned back to main(), and you then call .Result on it. You are now blocking that thread for most of the 250ms until that task returns its int result to .Result in main().
The way you have expressed it in the question, “awaited” does not equal “completed”.
The method Awaiter.Await is basically pointless. Outside of adding some overhead, the returned task will be functionally identical to the one passed in.
The only actual difference in code between simply returning the result of _actual.AddAsync(a, b) and awaiting it is that, if AddAsync throws an exception, if the method is async it will return a faulted task instead of throwing. So if that either can't happen, or if Proxy.AddAsync can safely throw itself in that situation, then simply return the value, no need to do anything. If you need to ensure that Proxy.AddAsync never throws an exception, and instead returns a faulted task if Proxy.AddAsync throws an excpetion, then you simply need to wrap the method in a try/catch and return a faulted exception in the catch block. You don't need to replicate any of the rest of the logic of the async state machine.
So assuming you want the same exception semantics as the behavior of the service's method, which I suspect you do, you can treat these methods exactly the same as you would a synchronous method, that is to say invoke the method with the appropriate parameters and return the result.

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

This question already has answers here:
How to implement interface method that returns Task<T>?
(4 answers)
Closed 6 years ago.
I am working with a third-party dll which exposes methods which return Task and Task<T>. I don't have any control over this assembly or the interface, and I assume the author assumed everything would need to be async since the naming of the methods are *Async() as shown below.
Given that, how do I properly implement the interface if I don't actually have any asynchronous code running?
public interface IFoo
{
Task DoWorkAsync();
Task<int> GetValueAsync();
}
My attempt was the following:
public class FooBar : IFoo
{
public async Task DoWorkAsync()
{
// Do Some Work
await Task.Yield();
}
public async Task<int> GetValueAsync()
{
// Do Some Work
var result = ...;
return Task.FromResult(result);
}
}
Additionally:
Was the author correct in exposing only methods that returned Task/Task<T>?
Was the author correct in suffixing method names with *Async()? Code analysis doesn't complain if I write an async method without appending Async to the name.
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.

How to cache data as long as Task executes?

private Data GetDefaultData()
{
var data = Task.Factory.StartNew(() => GetData());
return data.Result;
}
If GetData() executes in 100ms and I run one GetDefaultData() per 10ms. Is it correct that first 10 calls will use the same data.Result? GetData() collect Data inside lock statement. If not how to change the code to provide this opportunity?
Let's say, we have the first call GetDefaultData (GetData() executes in 100ms), and then we have 10 calls(GetDefaultData() per 10ms). I want that this rest of calls will get the same answer as the first one.
It sounds like you want the Lazy<T> class.
public class YourClass
{
private readonly Lazy<Data> _lazyData;
public YourClass()
{
_lazyData = new Lazy<Data>(() => GetData());
}
private Data GetDefaultData()
{
return _lazyData.Value;
}
public Data GetData()
{
//...
}
}
The first thread to call GetDefaultData() will run GetData() when it hits _lazyData.Value, all the rest of the threads will block on the call _lazyData.Value till the first thread finishes and use the result from that first thread's call. GetData() will only ever be called once.
If you don't want the call to block you can easily make a AsyncLazy<T> class that uses Threads internally.
public class AsyncLazy<T> : Lazy<Task<T>>
{
public AsyncLazy(Func<T> valueFactory) :
base(() => Task.Run(valueFactory))
{
}
public AsyncLazy(Func<Task<T>> taskFactory, bool runFactoryInNewTask = true) :
base(() => runFactoryInNewTask ? Task.Run(taskFactory) : taskFactory())
{
}
//This lets you use `await _lazyData` instead of doing `await _lazyData.Value`
public TaskAwaiter<T> GetAwaiter()
{
return Value.GetAwaiter();
}
}
Then your code becomes (I also made GetData an async function too, but the overloads of AsyncLazy let it be either or)
public class YourClass
{
private readonly AsyncLazy<Data> _lazyData;
public YourClass()
{
_lazyData = new AsyncLazy<Data>(() => GetData(), false);
}
private async Task<Data> GetDefaultData()
{
//I await here to defer any exceptions till the returned task is awaited.
return await _lazyData;
}
public Task<Data> GetData()
{
//...
}
}
EDIT: There are some possible issues with AsyncLazy, see here.
In short: No.
Each time you call GetDefaultData() a new task is started, so Data.Result will remain unchanged for the duration of GetData() and then contain what you assigned to it in GetData().
Also returning a value from a new Task object will do you no good - this is how multitasking works. Your code will continue to execute in the main thread, but you result value will only be set once the separate task is finished executing. Whether it contains lock statements or not.
Probably the ReaderWriterLock will suit you in this purpose. ReaderWriterLock is used to synchronize access to a resource. At any given time, it allows either concurrent read access for multiple threads, or write access for a single thread. This logic should be embaded into your GetData method probably, so that depening on some timeout it could either use writelock and hold it for this timeout time, otherwise use read operation.

How to create a Task which always yields?

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.

Categories