0

Code examples will use Xamarin Android.

I am extending the IntentService. It has few lifecycle methods. In particular, void OnHandleIntent(Intent intent) where you do actual work, and void OnDestroy() which is called by the system when it sees that the service finished working and it's time to destroy it. For IntentService, the end of its life is when OnHandleIntent returns.

Being an event-like method, it's OK to use async void OnHandleIntent. Consider following code

protected override async void OnHandleIntent(Intent intent)
{
    Debug.Out("OnHandleIntent Start");
    await Task.Run(async () => await Task.Delay(1000));
    Debug.Out("OnHandleIntent End");
}

protected override void OnDestroy(Intent intent)
{
    base.OnDestroy();
    Debug.Out("OnDestroy");
}

The output is:

Debug.Out("OnHandleIntent Start");
Debug.Out("OnDestroy");
Debug.Out("OnHandleIntent End");

At the same time, following (blocking) code works as expected

protected override void OnHandleIntent(Intent intent)
{
    Debug.Out("OnHandleIntent Start");
    Task.Run(async () => await Task.Delay(1000)).Wait();
    Debug.Out("OnHandleIntent End");
}

protected override void OnDestroy(Intent intent)
{
    base.OnDestroy();
    Debug.Out("OnDestroy");
}

The output is:

Debug.Out("OnHandleIntent Start");
Debug.Out("OnHandleIntent End");
Debug.Out("OnDestroy");

The question is - why does it happens?

5
  • Because the 2nd one is blocking. I don't understand the question, you seem to understand that the 2st one is blocking and the first is not. Commented Oct 10, 2019 at 11:27
  • 1
    The first one is blocking the execution of the OnHandleIntent method, in the sense that the code after the await will only execute once the task you're awaiting has completed. However, the code that called your OnHandleIntent will continue executing, because once your OnHandleIntent method reaches await, and that task isn't already completed, the method will return. So the calling code moves on and calls Destroy, before your task has completed. Commented Oct 10, 2019 at 11:28
  • 1
    BTW The use of Task.Run here is only for wasting resources and adding noise to the code. Task.Delay() already returns a task you can await or wait for Commented Oct 10, 2019 at 11:30
  • Possible duplicate of async/await - when to return a Task vs void? Commented Oct 10, 2019 at 11:38
  • @FreakyAli No, that question is different Commented Oct 10, 2019 at 12:10

1 Answer 1

1

async void methods cannot be awaited by the caller (because no Task is returned to wait for).

The first implementation will return before Delay is done; it will be executed as a fire and forget operation.


Btw.

await Task.Run(async () => await Task.Delay(1000))

can be

await Task.Delay(1000))
Sign up to request clarification or add additional context in comments.

Comments

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.