首页 > 解决方案 > 跳过等待会自动使异步代码同步吗?

问题描述

我有以下内容:

void SaveImage(Texture tex, string path)
{
    WritePngAsync(tex, path);
}

public static async void WritePngAsync(Texture tex, string path)
{
    // This code takes a long time to execute
    await PNG.WriteAsync(texture, path);
}

我这样称呼它:

for (int i = 0; i < 3; i++)
{
    var imageData = createData();// Create image data somehow
    SaveImage(imageData, $"{i}.png");
}

我期望发生的是循环会立即完成,因为即使WritePngAsync需要很长时间SaveImage也不会等待并且会立即返回。

我认为这会导致文件内容在调用时被覆盖的问题,但这我认为代码以某种方式自动转换为同步代码(即使似乎无法知道何时WriteAsync完成)。

await我省略且未声明SaveImage为这一事实是否async可以安全地用作同步函数?

换句话说,await从非异步方法调用 ed 函数是否会自动使代码同步执行并在完成时返回

或者同步是否在完成SaveImage之前立即返回WritePngAsync

从评论:

省略 await 确实会导致 SaveImage() 方法同步执行。但是,这不会传播到 WritePngAsync() 方法

那么这会导致在synchronous其函数调用完成之前返回吗?

如果在PNG.WriteAsync写入之前将纹理数据临时放入内存位置,那么后续调用是否可以将其数据放置在同一位置,从而在写入时覆盖前一个图像,或者SaveImage同步会阻止这种情况发生吗?

标签: c#asynchronousasync-await

解决方案


我省略了等待并且没有将 SaveImage 声明为异步的事实是否使它实际上是[同步的]?

async void,方法是危险的有几个原因。它们是异步的,但您的代码无法检测异步操作何时完成。此外,由于您的代码无法检测异步操作中的错误,因此任何异常都会直接在当前上下文中引发,这通常会导致应用程序关闭。这种行为似乎非常奇怪且不可取,直到您意识到async void方法是专门设计用作事件处理程序的,在其他情况下应避免使用

我期望发生的是循环会立即完成,因为即使 WritePngAsync 需要很长时间,SaveImage 也不会等待并且会立即返回。

是的,循环很快完成,当循环完成时,所有的PNG.WriteAsync操作都可能不完整。

我认为这会导致像这样调用时文件内容被覆盖的问题

这听起来很合理。您的代码无法知道WritePngAsync方法何时完成。


推荐阅读