How to call an async method from another method - c#

I am having a difficult time calling an async method from my current method.
Trying to do something like this:
int i;
public void Method1() {
while (statement1) {
~code~
Method2(i);
}
while (statement2) {
~code~
Method2(i);
}
}
public async void Method2(int i) {
if(statement){
~code~
await Task.Delay(2000);
}
else
{
~code~
await Task.Delay(2000);
}
}
So i want basically Method2 to be a method for controlling the flow (uses another method which changes pictures in pictureboxes), but I can't get it to work and when it works it never delays anything. Does anyone knows what I am doing wrong?
Method2 changes Method1's while statements eventually.

The best practice for async/await is to use async "all the way down" (unless you really and truly don't care about Method1 waiting for Method2 to complete).
It's possible to mix Task.Wait (or similar constructs) with async code, but it's a bad idea because it can lead to deadlocks.
The best thing here would be, as others have indicated, just make Method1 async too:
public async Task Method1() {
while (statement1) {
await Method2(i);
// ...
}
Note that you'll have to make Method1 return a Task too because otherwise you can't wait it:
public async Task Method2
This may be a case of the XY Problem though because there's no reason for the code sample you provide to be async in the first place (or even a separate method, for that matter) - you can just do Thread.Sleep instead. Also, the "if" statement is pointless because, based on what you've shown us, you delay for 2 seconds either way. It would be helpful if you could show a more substantial code sample so we can get a better sense of what you're trying to do so we can recommend whether async is even an appropriate solution here.
One final point: one of the purposes of async/await is to allow the calling thread to do other work while it's waiting for a result - for example, if you want to download a file without "hanging" the UI. I've seen plenty of cases where people use async/await in a way that essentially obviates the purpose though. For example:
static void Main(string[] args) {
// This is a terrible thing to do but it's for illustration purposes
Task task = Method1();
task.Wait();
// Some other work
}
private static async Task Method1() {
await Method2();
// Some other work
}
private static async Task Method2() {
await Method3();
// Some other work
}
private static async Task Method3() {
await Task.Delay(1000);
}
This is a pretty dumb illustration, granted, but in this case the async/await is completely pointless because it's just doing each action sequentially anyway.

For another method to be able to await Method2 the latter must return have a return type of Task or Task (and not void):
public async Task Method2(int i) {
if(statement){
~code~
await Task.Delay(2000);
}
else
{
~code~
await Task.Delay(2000);
}
Method1 should then be marked as async and await Method2:
public async void Method1() {
while (statement1) {
~code~
await Method2(i);
}
while (statement2) {
~code~
await Method2(i);
}
}

You should make Method1 also asyncronous and add await operator for Method2 call:
public async Task Method1() {
while (statement1) {
~code~
await Method2(i);
}
while (statement2) {
~code~
await Method2(i);
}
}
public async Task Method2(int i) {
if(statement){
~code~
await Task.Delay(2000);
}
else
{
~code~
await Task.Delay(2000);
}
}
If you need Method1 to be syncronous for some reason, you should call Wait() on task returned from Method2. However it's considered as bad practice because you loose advantage of .NET thread pool.

Related

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.

Non-Async Method In Async Call Stack [duplicate]

This question already has answers here:
Why use async and return await, when you can return Task<T> directly?
(9 answers)
Closed 5 years ago.
Sorry for a terrible title, I just wanted to confirm that I am making the correct assumptions.
Say I have 3 methods that are simplified to:
public async Task Method1()
{
var obj = await Method2();
//do work on obj
}
public Task<object> Method2()
{
//do some work
return Method3();
}
public async Task<object> Method3()
{
//do async work
return obj;
}
Method2 above does no async work internally, but is in my async stack. It could be rewritten as:
public async Task<object> Method2()
{
//do some work
return await Method3();
}
Am I correct that, as Method2 doesn't actually do async work, that it is better to leave it as a non-async method? My thought is that I'm saving the overhead of creating an extra state machine to hold the thread's resources when it is not needed.
Correct. You can return the Task directly from a method without adding the async/await keywords if the method does not need to await any result (ie. consume the result of a task or wait for a task to complete to be able to do some execution). That returned Task can then be awaited by a caller further down the call stack. This can save a little overhead and make for slightly less code (although that amount of code is actually trivial).
You often see this with pass through or convenience methods.

Nested Task<T> calls without async/await

This is kind of related to the following post: Why use Async/await all the way down
I am curious what happens in the following scenario:
Updated due to comment:
async Task FooAsync()
{
await Func1();
// do other stuff
}
Task Func1()
{
return Func2();
}
async Task Func2()
{
await tcpClient.SendAsync();
// do other stuff
}
Does this whole process becomes a blocking call? Or because Func1() is actually awaited on, the UI can go and work on something else? Ultimately is it necessary to add the async/await on Func1()? I've played around with it but I don't actually notice any difference, hence the question. Any insight would be great, thanks!
Async and await are just compiler features.
Without await calling async method will cause it to execute synchronous (blocking) way..
When you are writing await all code bellow await is wrapped in Task.ContinueWith() Method by compiler automaticly, this means that when task is finished code below is executed later
public async Task<int> method2(){
return Task.FromResult(1);
}
public void method1(){
await method2()
Console.WriteLine("Done");
}
will translate something like :
public Task<int> method2(){
return Task.FromResult(1);
}
public void method1(){
method2().ContinueWith(x => {
Console.WriteLine("Done");
});
}
The only problem of not making Func1 and async method and not awaiting Func2 in it is that any thrown exception won't show Func1.
The bottom line is that await works on awaitables and Task/Task<T> are awaitables.

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.

Locking with nested async calls

I am working on a multi threaded WindowsPhone8 app that has critical sections within async methods.
Does anyone know of a way to properly use semaphores / mutexes in C# where you are using nested async calls where the inner method may be acquiring the same lock that it already acquired up the callstack? I thought the SemaphoreSlim might be the answer, but it looks like it causes a deadlock.
public class Foo
{
SemaphoreSlim _lock = new SemaphoreSlim(1);
public async Task Bar()
{
await _lock.WaitAsync();
await BarInternal();
_lock.Release();
}
public async Task BarInternal()
{
await _lock.WaitAsync(); // deadlock
// DO work
_lock.Release();
}
}
Recursive locks are a really bad idea (IMO; link is to my own blog). This is especially true for async code. It's wicked difficult to get async-compatible recursive locks working. I have a proof-of-concept here but fair warning: I do not recommend using this code in production, this code will not be rolled into AsyncEx, and it is not thoroughly tested.
What you should do instead is restructure your code as #svick stated. Something like this:
public async Task Bar()
{
await _lock.WaitAsync();
await BarInternal_UnderLock();
_lock.Release();
}
public async Task BarInternal()
{
await _lock.WaitAsync();
await BarInternal_UnderLock();
_lock.Release();
}
private async Task BarInternal_UnderLock()
{
// DO work
}
Here's what I did in such a situation (still, I'm not experienced with tasks, so don't beat me ;-)
So basically you have move the actual implementation to non locking methods and use these in all methods which acquire a lock.
public class Foo
{
SemaphoreSlim _lock = new SemaphoreSlim(1);
public async Task Bar()
{
await _lock.WaitAsync();
await BarNoLock();
_lock.Release();
}
public async Task BarInternal()
{
await _lock.WaitAsync(); // no deadlock
await BarNoLock();
_lock.Release();
}
private async Task BarNoLock()
{
// do the work
}
}
First, read through Stephen Cleary's blog post, which he linked to in his answer. He mentions multiple reasons, such as uncertain lock state and inconsistent invariants, which are associated with recursive locks (not to mention recursive async locks). If you can do the refactoring he and Knickedi describe in their answers, that would be great.
However, there are some cases where that type of refactoring is just not possible. Fortunately, there are now multiple libraries which support nested async calls (lock reentrance). Here are two. The author of the first has a blog post where he talks more about it.
https://github.com/neosmart/AsyncLock
https://github.com/mysteryjeans/Flettu/
You can incorporate it into your code as such (using the first library in this example):
public class Foo
{
AsyncLock _lock = new AsyncLock();
public async Task Bar()
{
// This first LockAsync() call should not block
using (await _lock.LockAsync())
{
await BarInternal();
}
}
public async Task BarInternal()
{
// This second call to LockAsync() will be recognized
// as being a reëntrant call and go through
using (await _lock.LockAsync()) // no deadlock
{
// do work
}
}
}
Disclaimer: I'm the author of the NuGet package I mention here.
There have been several attempts at a recursive/reentrant async lock (some are listed below) but only one of them succeeds in providing all three of these at once:
Asynchronicity
Reentrance
Mutual exclusion
As of this writing, the only correct implementation that I know of is:
https://www.nuget.org/packages/ReentrantAsyncLock/
The package documentation shows how to use it. Using it in your code would look like this:
public class Foo
{
ReentrantAsyncLock _lock = new ReentrantAsyncLock();
public async Task Bar()
{
await using (await _lock.LockAsync(CancellationToken.None))
{
await BarInternal();
}
}
public async Task BarInternal()
{
await using (await _lock.LockAsync(CancellationToken.None)) // No deadlock
{
// DO work
}
}
}
I'm sure everyone knows what asynchronicity is.
Your code is an example of reentrance.
This is an example of mutual exclusion:
var gate = new object();
var value = 0;
var tasks = new List<Task>();
for (var i = 0; i < 1000; i++)
{
var task = Task.Run(() =>
{
lock (gate)
{
value++; // Without the lock this is a race condition
}
});
tasks.Add(task);
}
Task.WhenAll(tasks).Wait();
Debug.Assert(value == 1000);
The regular lock keyword in C# gives reentrance and mutual exclusion.
SemaphoreSlim and a dozen other things give asynchronicity and mutual exclusion.
But it has been difficult for people to get all three together at once.
For example, Stephen Cleary linked to his proof of concept in his answer. But his fails these tests:
https://github.com/matthew-a-thomas/cs-reentrant-async-lock/blob/ece6e461c26f005da2122185cb9c5b884968f98a/ReentrantAsyncLock.Tests/ReentrantAsyncLockClass.cs
(Keep in mind those tests were originally written for the ReentrantAsyncLock NuGet package, that's why some things are commented out that don't make sense for Stephen Cleary's RecursiveAsyncLock, and that's why the test file has ReentrantAsyncLock in its name. Compare that test file to the equivalent on the main branch and you'll see what I mean.)
Of course he has never claimed that it would but has only ever cautioned people against using it. So this isn't a ding against Stephen. I'm just giving an example of how someone can make an async lock and at first glance it looks like it gives all three of the things I listed above when in fact it has trouble putting the second two things together.
Similar things can be said for all of these:
https://github.com/neosmart/AsyncLock - these two tests deadlock
https://github.com/mysteryjeans/Flettu/ - this test sometimes deadlocks, sometimes fails with a mismatched count, and sometimes fails with a semaphore count exception
https://github.com/jasonkuo41/CellWars.Threading.AsyncLock - both of these tests fail with mismatched values
You can use the System.Threading.ReaderWriterLockSlim (doc), which has a support recursion flag:
ReaderWriterLockSlim _lock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
async Task Bar()
{
try
{
_lock.EnterReadLock();
await BarInternal();
}
finally
{
if (_lock.IsReadLockHeld)
_lock.ExitReadLock();
}
}
async Task BarInternal()
{
try
{
_lock.EnterReadLock();
await Task.Delay(1000);
}
finally
{
if (_lock.IsReadLockHeld)
_lock.ExitReadLock();
}
}
Still you should be very careful with recursion because it is very difficult to control which thread took a lock and when.
The code in the question will be result in a deadlock because it tries to acquire the lock twice, something like:
await _lock.WaitAsync();
await _lock.WaitAsync(); --> Will result in exception.
While flagging the ReaderWriterLockSlim in SupportsRecursion will not throw an exception for this weird code:
_lock.EnterReadLock();
_lock.EnterReadLock();

Categories