我刚开始学习async / await。
Stephen Cleary有这篇文章: https://blog.stephencleary.com/2013/11/there-is-no-thread.html
我对I / O了解不多但是......有人可以解释一下如何对不使用I / O的操作应用async / await逻辑吗?
假设我们有一个string[]
并想要反转此数组中的所有字符串。
async Task<string> ReverseAsync(string s)
{
char[] charArray = s.ToCharArray();
Array.Reverse(charArray);
return new string(charArray);
}
然后我想“并行”为数组中的每个元素调用此方法。 我知道像这样的代码不是有效的,但如何使用async / await实现呢?
答案 0 :(得分:5)
有人可以解释一下如何为不使用I / O的操作应用async / await逻辑吗?
您可以在.NET中使用新的async/await
来简化并发操作,而不会有任何关于旋转潜在昂贵线程的麻烦。无论操作是CPU绑定还是IO绑定,都可以使用async/await
。
语法大致相同,只是对于CPU绑定操作,您通常明确地调用Task.Run()
或其版本。 TasK
可以被认为是表示并发操作的高级构造,而不是 Thread
的同义词。 Task.Run
将在线程池中的一个可重用线程中执行代码,该线程很可能已在运行。操作完成后,将返回池中。
e.g。
await Task.Run (() => CalculatePrimeNumbersAsync (10000));
在你的场景中,你应该尝试尽可能靠近callstack的顶部调用Task.Run()。这使你的代码:
然后我想&#34;并行&#34;为数组中的每个元素调用此方法。我知道像这样的代码不是有效的,但如何使用async / await实现呢?
您可能无法更改实现,但是您可以通过调用方法的方式来使用并发性。
所以给出你的代码:
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或实体框架,请不要使用Task.Run()。
答案 1 :(得分:0)
使用Parallel.ForEach执行方法并反转数组中的许多字符串。我建议您批量处理字符串,例如10 x 10或100 x 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();
});