[英]Async/Await without I/O
我刚刚开始学习异步/等待。
斯蒂芬·克莱里(Stephen Cleary)上有这篇文章: https : //blog.stephencleary.com/2013/11/there-is-no-thread.html
我对I / O知之甚少,但是...有人可以解释一下我如何为不使用I / O的操作应用异步/等待逻辑吗?
假设我们有一个string[]
并想反转此数组中的所有字符串。
async Task<string> ReverseAsync(string s)
{
char[] charArray = s.ToCharArray();
Array.Reverse(charArray);
return new string(charArray);
}
然后,我想为数组中的每个元素“并行”调用此方法。 我知道这样的代码将无效,但是如何使用async / await来实现呢?
有人可以解释一下我如何将异步/等待逻辑应用于不使用I / O的操作吗?
您可以在.NET中使用新的async/await
来简化并发操作,而不必费解所有可能浪费昂贵线程的麻烦。 无论操作是受CPU限制还是受IO限制,都可以使用async/await
。
除了对CPU绑定的操作,通常会显式调用Task.Run()
或其版本,语法几乎相同。 TasK
可以看作是表示并发操作的高级构造,而不是 Thread
的同义词。 Task.Run
将在线程池中最有可能已经在运行的可重用线程之一中执行代码。 操作完成后,它将返回到池中。
例如
await Task.Run (() => CalculatePrimeNumbersAsync (10000));
在您的方案中,您应该尝试尽可能靠近调用堆栈顶部的位置调用Task.Run()。 这使您的代码:
然后,我想为数组中的每个元素“并行”调用此方法。 我知道这样的代码将无效,但是如何使用async / await来实现呢?
更改实现可能没有什么可做的,但是您可以通过调用method的方式使用并发。
因此,鉴于您的代码:
async Task<string> ReverseAsync(string s)
{
char[] charArray = s.ToCharArray();
Array.Reverse(charArray);
return new string(charArray);
}
您将这样称呼它(假设它是WinForms中的按钮单击处理程序):
async void OnButtonClicked (object sender, System.EventArgs e)
{
var reversed = await Task.Run(() => ReverseString ("Miss Piggy is a Muppet"));
}
再次注意,我们使用Task.Run()
因为客户端代码知道ReverseString
受CPU限制。 如果要调用某些I / O绑定,例如WCF或Entity Framework,请不要使用Task.Run()。
使用Parallel.ForEach执行方法并反转数组中的许多字符串。 我建议您根据字符串的大小分批处理字符串,例如10×10或100×100。 因为从线程池中为小型任务调度线程的开销很大。 批处理项目时,您将具有足够大的任务,并且此开销可以忽略不计。
int batchSize = 10;
Parallel.ForEach(array.Select((x,i) => new {value = x, index= i})
.GroupBy(a => a.index/batchSize),
(item) =>
{
array[item.index] = item.value.Reverse();
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.