Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using async await inside void method

I have method with signature I cannot change. It should be

protected override void OnInitialize()

Using Windows 8 Metro API I need to check if file exists and read it, inside this NoSignatureChange method. Using PlainOldCSharp, I would write something like

protected override void OnInitialize()
{
  ...
  try
  {
    var file = folder.OpenFile(fileName);
    fileExists=true;
  }
  catch(FileNotFoundException)
  {
    fileExists=false
  }
}

Remember, in Windows 8 API only way to check if file exists is handling FileNotFoundException Also, in Windows 8 API all FileIO API is async, so I have only file.OpenFileAsync method.

So, the question is: How should I write this code using folder.OpenFileAsync method in Windows 8 API without changing signature of containing method

like image 709
Alex Sorokoletov Avatar asked Aug 03 '12 21:08

Alex Sorokoletov


People also ask

Can we use async await in void method?

You cannot await an async/void method.

How async await works internally?

The async keyword turns a method into an async method, which allows you to use the await keyword in its body. When the await keyword is applied, it suspends the calling method and yields control back to its caller until the awaited task is complete. await can only be used inside an async method.

Is async void fire and forget?

The async void case is a “fire and forget”: You start the task chain, but you don't care about when it's finished. When the function returns, all you know is that everything up to the first await has executed. Everything after the first await will run at some unspecified point in the future that you have no access to.

Does async await use thread pool?

The async and await keywords don't cause additional threads to be created. Async methods don't require multithreading because an async method doesn't run on its own thread. The method runs on the current synchronization context and uses time on the thread only when the method is active.


1 Answers

You can still make a void method async:

protected async void CannotChangeSignature()
{
    ...
}

Valid return types for an async method are:

  • void
  • Task
  • Task<T>

However, if you want to make it actually block, then you're basically fighting against the platform - the whole point is to avoid blocking.

You say you can't change the signature - but if you're relying on this blocking then you've got to change the way you approach coding.

Ideally you should change the signature to Task<bool>:

protected async Task<bool> CannotChangeSignature()
{
  ...
  try
  {
    await ApplicationData.Current.LocalFolder.GetFileAsync(fileName);
    return true;
  }
  catch(FileNotFoundException)
  {
    return false;
  }
}

EDIT: If you really need a blocking one, you'll just have to call AsTask().Wait(), catch the AggregateException and check whether it contains a FileNotFoundException. It really is pretty horrible though... can you not design around this so that it doesn't need to be blocking? For example, start checking for the file, and show an error (or whatever) if and when you find it doesn't exist.

like image 110
Jon Skeet Avatar answered Oct 21 '22 19:10

Jon Skeet