繁体   English   中英

没有I / O的异步/等待

[英]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()。 这使您的代码:

  1. 更直观
  2. 显然,被调用的操作是异步的
  3. 客户端代码可以完全控制根任务的创建
  4. 为客户端代码提供捕获当前上下文的机会(在GUI代码中特别有用)

然后,我想为数组中的每个元素“并行”调用此方法。 我知道这样的代码将无效,但是如何使用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.

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