【问题标题】:Cancel Parallel.ForEach or use async await取消 Parallel.ForEach 或使用异步等待
【发布时间】:2014-07-29 13:59:54
【问题描述】:

我有这个活动:

private void  TextBoxSearchText_TextChanged(object sender, TextChangedEventArgs e)
{
    searchText();
}

我想取消这个并行方法并在文本框文本更改时开始一个新的方法,并且还希望我的文本框能够响应我的新文本输入,在结果进入列表框之前锁定。

List<TextList> oSelected;
private void searchText()
{
string strSearchText = TextBoxSearchText.Text;
    oSelected = new List<TextList>();            
    Parallel.ForEach(oTextList, item  =>
    {
        Match myMatch = Regex.Match(item.EnglishText.ToString(), "\\b" + strSearchText.ToString().ToLower() + @"\w*", RegexOptions.IgnoreCase);
        if (!myMatch.Success)
        {
            return;
        }

        oSelected.Add(new TextList
        {
            Id = item.Id,
            EnglishText = item.EnglishText
        });
    });

    ListBoxAllTexts.ItemsSource = oSelected;
}

是否可以使用 async 和 awiat 来完成这项工作? 哪一个更适合在近 100 万行文本中搜索文本? 我读了很多关于 async 和 await 但我不明白如何在我的工作中使用它。 谢谢

【问题讨论】:

  • 我更新了我的问题,添加了字符串 strSearchText 以了解如何将其实现到 searchText() 方法中以从文本框中获取新文本。为什么我不能在我的方法中创建新字符串?

标签: c# asynchronous parallel.foreach async-await


【解决方案1】:

由于您的工作受 CPU 限制,因此您应该使用并行代码来进行实际搜索。但是,您可以使用Task.Run 将并行工作封装在async/await 思维模式中:

private async void TextBoxSearchText_TextChanged(object sender, TextChangedEventArgs e)
{
  ListBoxAllTexts.ItemsSource = await Task.Run(() => searchText(TextBoxSearchText.Text));
}

这将使您的 UI 保持响应。

要取消,use a CancellationTokenSource。附带说明一下,您无法像当前尝试那样从并行循环中更新List&lt;T&gt;,因为List&lt;T&gt; 不是线程安全的。在这种情况下,我建议您改用 PLINQ:

private CancellationTokenSource _cts;
private async void TextBoxSearchText_TextChanged(object sender, TextChangedEventArgs e)
{
  if (_cts != null)
    _cts.Cancel();
  _cts = new CancellationTokenSource();
  var strSearchText = TextBoxSearchText.Text;
  ListBoxAllTexts.ItemsSource = await Task.Run(
      () => searchText(strSearchText, _cts.Token));
}

private List<TextList> searchText(string strSearchText, CancellationToken token)
{
  try
  {
    return oTextList.AsParallel().WithCancellation(token)
        .Where(item => Regex.IsMatch(item.EnglishText.ToString(), "\\b" + strSearchText.ToLower() + @"\w*", RegexOptions.IgnoreCase))
        .Select(item => new TextList
        {
          Id = item.Id,
          EnglishText = item.EnglishText
        })
        .ToList();
  }
  catch (OperationCanceledException)
  {
    return null;
  }
}

另外,考虑通过延迟后才开始搜索来限制用户输入。 Rx 是最好的方法。

【讨论】:

  • 谢谢。我做了一些有问题的更改,请检查。
  • 更新添加string strSearchText作为方法参数。
  • 添加方法参数面临这个错误:Player.MainWindow.searchText(string, System.Threading.CancellationToken)': 并非所有代码路径都返回值
  • @MajidPoureftekhari:已修复。你可能想考虑买一本关于 C# 的书。
  • 错误:在 mscorlib.dll 中发生“System.InvalidOperationException”类型的未处理异常附加信息:调用线程无法访问此对象,因为不同的线程拥有它。在 TextBox 文本更改事件上
猜你喜欢
  • 2020-04-23
  • 1970-01-01
  • 2020-10-07
  • 2023-01-27
  • 1970-01-01
  • 1970-01-01
  • 2014-09-15
  • 1970-01-01
  • 2021-11-29
相关资源
最近更新 更多