[英]Asynchronous Programming: await inside a function that is not async
首先是问题:我可以在未标记为异步的函数中使用await吗?
现在的细节。 我正在读这篇文章Hololens-捕捉照片......正如你所看到的那样,作者发布了一些代码。 其中就是这个
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;
}
现在注意getFolderPath如何返回void(作为事件处理程序),但是文档说这些方法是无法等待的。 作者改为等待使用while循环。
但是如果我这样做会怎么样
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);
//.....
}
我可以这样做吗? (注意Start()不是Async)
人们往往会忘记async
和await
的背后。
不,你不能在一个非async
的方法中await
,但你可以在返回的Task
上调用ContinueWith
并提供仅在任务完成时执行的显式延续:
class Example
{
public void Start()
{
getFolderPath()
.ContinueWith(t =>
{
Console.WriteLine("...");
});
}
async Task getFolderPath()
{
await Task.Delay(1000);
}
}
这相当于
class Example
{
public async Task Start()
{
await getFolderPath();
Console.WriteLine("...");
}
async Task getFolderPath()
{
await Task.Delay(1000);
}
}
您不能await
不将方法标记为async
情况下await
函数调用。 所以你的第二个例子不会编译。 但您可以将Start方法标记为async
。
Async await
是一种等待执行函数的非阻塞方法。 在这种情况下,执行将在GetFolderPath
方法中的await处停止,但是这将等待,Start方法中的执行将继续。 我假设,因此,作者使用while loop
等待getFolderPath
的执行完成。
你的第一个问题的答案是否定的,你不能 。 从官方文档
await
只能在async
关键字修改的异步方法中使用。 通过使用async修饰符定义并且通常包含一个或多个await表达式的这种方法称为异步方法。
如果要在start方法中等待执行异步方法getFolderPath
,则需要将签名更新为
public async Task Start ()
{
await getFolderPath();
Debug.Log("About to call CreateAsync");
PhotoCapture.CreateAsync(false, OnPhotoCaptureCreated);
Debug.Log("Called CreateAsync");
}
在async await
上下文中, Task
作为返回类型,意味着任务不返回值,这在同步方法中等效于void
。 例如,如果您需要从异步任务返回一个string
,则需要使用public async Task<string> GetFoo()
。
总的来说,我认为您正在查看的示例中的代码需要进行一些审核。
您可以显式等待GetFolderPath
方法完成:
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);
//.....
}
但是之后你将异步方法转换为同步方法 ,因为Wait
是一种阻塞方法(但这就是在while循环中发生的事情)。
如果您的目标是使操作保持异步,则必须遵循DanielOrmeño的建议:
async Task Start ()
{
await getFolderPath();
Debug.Log("About to call CreateAsync");
PhotoCapture.CreateAsync(false, OnPhotoCaptureCreated);
Debug.Log("Called CreateAsync");
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.