繁体   English   中英

异步编程:等待非异步的函数内部

[英]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)

人们往往会忘记asyncawait的背后。

不,你不能在一个非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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM