Reputation: 9912
First the question: Can I use await inside a function that is not marked as async??
Now the details. I was reading this post Hololens- Capturing Photo... and as you can see the author posted some code. Among it this
void Start ()
{
getFolderPath();
while (!haveFolderPath)
{
Debug.Log("Waiting for folder path...");
}
Debug.Log("About to call CreateAsync");
PhotoCapture.CreateAsync(false, OnPhotoCaptureCreated);
Debug.Log("Called CreateAsync");
}
async void getFolderPath()
{
StorageLibrary myPictures = await Windows.Storage.StorageLibrary.GetLibraryAsync(Windows.Storage.KnownLibraryId.Pictures);
Windows.Storage.StorageFolder savePicturesFolder = myPictures.SaveFolder;
Debug.Log("savePicturesFolder.Path is " + savePicturesFolder.Path);
folderPath = savePicturesFolder.Path;
haveFolderPath = true;
}
Now notice how the getFolderPath returns void (as an event handler) but the documentation says that these methods can't be awaited. The author instead await by using a while loop.
But what if I do this
void Start ()
{
await getFolderPath();
Debug.Log("About to call CreateAsync");
PhotoCapture.CreateAsync(false, OnPhotoCaptureCreated);
Debug.Log("Called CreateAsync");
}
//Notice how now it returns Task
async Task getFolderPath()
{
StorageLibrary myPictures = await Windows.Storage.StorageLibrary.GetLibraryAsync(Windows.Storage.KnownLibraryId.Pictures);
//.....
}
Can I do this? (notice that Start() is not Async)
Upvotes: 3
Views: 4433
Reputation: 48230
People tend to forget what's behind async
and await
.
No, you can't await
in a method that's not async
but you can call ContinueWith
on the returned Task
and provide explicit continuation that executes only when the task is complete:
class Example
{
public void Start()
{
getFolderPath()
.ContinueWith(t =>
{
Console.WriteLine("...");
});
}
async Task getFolderPath()
{
await Task.Delay(1000);
}
}
That's equivalent to
class Example
{
public async Task Start()
{
await getFolderPath();
Console.WriteLine("...");
}
async Task getFolderPath()
{
await Task.Delay(1000);
}
}
Upvotes: 3
Reputation: 2778
The answer to your first question is No, you can't. From the official documentation
await
can only be used in an asynchronous method modified by theasync
keyword. Such a method, defined by using the async modifier and usually containing one or more await expressions, is referred to as an async method.
If you want to await the execution of the async method getFolderPath
inside the start method, you need to update the signature to be
public async Task Start ()
{
await getFolderPath();
Debug.Log("About to call CreateAsync");
PhotoCapture.CreateAsync(false, OnPhotoCaptureCreated);
Debug.Log("Called CreateAsync");
}
In the async await
context, Task
as a return type, means that the task does not return a value, which is equivalent to void
in the synchronous approach. if for example, you needed to return an string
from an asynchronous task, you would need to have public async Task<string> GetFoo()
.
Overall, I think the code you from the example you are looking at needs some reviewing.
Upvotes: 0
Reputation: 3285
You could explicitly wait on the GetFolderPath
method to finish:
void Start ()
{
getFolderPath().Wait();
Debug.Log("About to call CreateAsync");
PhotoCapture.CreateAsync(false, OnPhotoCaptureCreated);
Debug.Log("Called CreateAsync");
}
//Notice how now it returns Task
async Task getFolderPath()
{
StorageLibrary myPictures = await Windows.Storage.StorageLibrary.GetLibraryAsync(Windows.Storage.KnownLibraryId.Pictures);
//.....
}
But then you are turning the asynchronous method in a synchronous one, since Wait
is a blocking method (but that is what happens in the while loop anyway).
If your aim is to keep the operation asynchronous, you have to go with Daniel Ormeño's suggestion:
async Task Start ()
{
await getFolderPath();
Debug.Log("About to call CreateAsync");
PhotoCapture.CreateAsync(false, OnPhotoCaptureCreated);
Debug.Log("Called CreateAsync");
}
Upvotes: 0
Reputation: 231
You can not await
function calls without marking the method as async
. So your second example will not compile. But you can mark the Start method as async
.
Async await
is a non blocking method to wait for execution of functions. In this case, the execution will stop at the await in the GetFolderPath
method, but while this will wait, the execution in the Start method will continue. I assume, that because of this, the author uses the while loop
to wait for the execution of getFolderPath
to finish.
Upvotes: 0