0

I have a class that awaits an asynchronous thread to return. What I do is launch a while loop and check every second where it's at.

public class AsychronousThingy
{
   public bool IsComplete{get;private set;}
   public string Result {get;private set;}
   public void StartDoingThings(){
       IsComplete = false;
       // kick of an asynchronous thread to do stuff...
   }
   private void OnComplete(){
       IsComplete = true;
       Result = "magical result";
   }
}
public class ActionExecutor{
    public async Task<CustomThingyTaskResult> DoStuff(){
        var thing = new AsychronousThingy();
        thing.StartDoingThings();

        // this returns instantly...?
        while(!thing.IsComplete){
             await Task.Delay(1000);
        }

        // do stuff once the 'thing' is complete.
        return new CustomThingyTaskResult(thing.Result);
    }
}
class Program{
    public static void Main(){
         var exec = new ActionExecutor();
         var returnValue = await exec.DoStuff();
    }
}

I'm unsure why it is returning instantly. Is this an issue - can you not use Task.Delay inside a loop? Odd.

I am sure that this is returning before it is complete as when I console.writeline from the OnComplete event of my async class it actually completes after my main method has finished.

3
  • 1
    DoStuff should return a Task Commented Aug 20, 2014 at 3:52
  • Apologies it does... very bad pseudo example. Updated. Commented Aug 20, 2014 at 4:42
  • 2
    Your updated code doesn't compile, because await can't be used in Main. Commented Aug 20, 2014 at 12:30

2 Answers 2

3

Because DoStuff() is async, it finishes asynchronously when called. This explains why the main method has already returned when the asynchronous action completes. However, since DoStuff returns void, you cannot await it as you would normally do. You can change the return type to Task though, and then await it.

There is nothing wrong about awaiting in a loop, except that it is more efficient to use events (or other synchronization mechanisms). Also, AsynchronousThingy could likely be formulated in terms of a Task as well :-)

Sign up to request clarification or add additional context in comments.

1 Comment

You should be using Task instead - void cannot be awaited. msdn.microsoft.com/en-us/library/…
1

Your Main() function is void. As a result, after first hit to actual async action (in your example it is await Task.Delay(1000)) it returns control to its caller. So, you can change the signature of Main() function as follows:

public static async Task Main() {...}

And then await on it.

Or, as alternative, you may not use async keyword on it and use old Wait/Result:

public static void Main()
{
...
var returnValue = exec.DoStuff().Result;
// Or, if there is a SynchronizationContext
returnValue = Task.Run(() => exec.DoStuff()).Result; // This may prevent dead locks that can occur in previous line
}

1 Comment

This is actually close to the correct answer - my example is a pseudo example; but the main problem was that the parent class's parent class (ie on above my example above's Main method) was not running as a task. Fixing this resolved it and made the method maintain control at the await.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.