gpt4 book ai didi

c# - 编写一个可以等待的异步进程

转载 作者:太空狗 更新时间:2023-10-29 22:56:58 27 4
gpt4 key购买 nike

我一直在研究如何将我的(同步)算法转换为异步算法。 (轻敲)首先,要明确一点,这个问题不是关于“Async 和 Await 是做什么的”(我已经阅读了 Stephen Cleary 的优秀文章,例如 Async and Await(如果有人有兴趣阅读链接-信息量很大)

我也已经阅读了“C# in a nutshell”中关于并发的章节。

这个问题也不是关于异步函数如何使用 await 来调用函数的问题。我已经知道了。

不幸的是,在我读到的几乎所有内容中,await Task.Delay(10) 都用于“创建异步函数”。例如:

public async Task<int> GetResult()
{
int result= await GiveMeTheInt();

}
public async Task<int> GiveMeTheInt() //<--is async needed here? (oops! I just realize it is...
{
await Task.Delay(100);
return(10);
}

例如,在这个例子中,我已经理解了 GetResult() 函数中异步等待的魔力,但是 GiveMeTheInt() 的实现并不是很有用。(他们只需将 Delay 作为通用异步函数放置即可)

所以我的问题是关于“GiveMeTheInt”类型的问题(不是调用它们的人)。

问题

如果我在函数中编写的算法到目前为止一直是同步的,我如何才能将其转换为异步使用?


这不是一个重复的问题,我发现最接近的是 Turning a Syncronous method async其中发帖人被告知使用他已经存在的方法的异步版本。就我而言,这不存在。

我的算法主要由图像处理组成,因此本质上是扫描大型阵列并更改每个像素的值。有点像

void DoSomethingToImage(int[,] Image)
{
for(int i=0;i<width;i++)
for(int j=0;j<height;j++)
{
Image[i,j]=255;
}
}

(这是一个虚构的例子,操作当然不同)

我得到的最接近的答案是将函数放在 Task.Run() 中,但我不确定这是否是实现它的方法。

任何帮助将不胜感激

最佳答案

那么看看你的方法:

void DoSomethingToImage(int[,] image)
{
for (int i = 0; i < width; i++)
{
for (int j = 0; j < height; j++)
{
image[i, j] = 255;
}
}
}

这是异步的吗?明显不是。这只是 CPU 密集型工作,会让处理器忙一阵子。因此,自己制作异步并不是一个好的选择。它应该同步运行。

如果您从应用程序的异步部分使用它怎么办?您当然不希望用户界面阻塞,因为您正在迭代大量像素。所以解决方案是将工作加载到另一个线程。您可以使用 Task.Run 执行此操作:

await Task.Run(() => DoSomethingToImage(image));

因此,无论何时从异步方法调用 DoSomethingToImage 方法,您都会这样写。现在,如果您仅在异步上下文中使用该方法,您可能会争辩说将 Task.Run 移动到函数中可能是有意义的:

Task DoSomethingToImageAsync(int[,] image)
{
return Task.Run(() => { … });
}

这是个好主意吗?一般来说不是,因为现在你让这个方法看起来是异步的,而实际上它不是。它所做的只是生成一个新线程来完成工作,然后等待线程完成。因此,现在您隐藏该部分,并使执行高度同步工作的方法决定应启动线程。这很少是个好主意。保持方法原样并没有错,以表明它是同步的,并让调用代码负责决定如何该代码应该运行。

If I have an algorithm written in a function that so far has been synchronous, how can I convert this to be used asynchronously?

因此,回到您的实际问题,这实际上很难回答。答案可能就是这样:“视情况而定”

如果一个方法做 CPU 绑定(bind)工作,你最好保持同步,让调用代码决定如何运行它。如果您主要从事与其他接口(interface)(网络、文件系统等)交互的 I/O 工作,那么这是使其成为异步的一个很好的候选者,尤其是考虑到其中许多接口(interface)将已经提供了与他们通信的异步方式。


关于“这里需要异步吗?”的最后一点说明您的代码中的问题:您需要 async 关键字 whenever 您想要在其中使用 await 。仅仅存在 async 关键字并不能使方法异步(即使返回类型也没有表明这一点)。

关于c# - 编写一个可以等待的异步进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46663296/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com