C# 中是否存在异步正则表达式?它们对我的情况有帮助吗?

2024-04-30

我的应用程序使用正则表达式并行搜索许多文件,await Task.WhenAll(filePaths.Select(FindThings));

代替FindThings,它花费大部分时间执行正则表达式搜索,因为这些文件的大小可能有数百MB。

static async Task FindThings(string path) {
    string fileContent = null;
    try
    {
        using (var reader = File.OpenText(path))
            fileContent = await reader.ReadToEndAsync();
    }
    catch (Exception e)
    {
        WriteLine(lineIndex, "{0}: Error {1}", filename, e);
        return;
    }

    var exitMatches = _exitExp.Matches(fileContent);

    foreach (Match exit in exitMatches)
    {
        if (_taskDelay > 0)
            await Task.Delay(_taskDelay);

    // [...]
  • 是否有正则表达式的异步版本或任何方法可以使其与任务正确配合?

为什么这很重要

我收到的很多回复表明我没有澄清为什么这很重要。以这个示例程序(使用 Nitro.Async 库)为例:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Nito.AsyncEx;

namespace Scrap
{
    class Program
    {
        static void Main(string[] args)
        {
            AsyncContext.Run(() => MainAsync(args));
        }

        static async void MainAsync(string[] args)
        {
            var tasks = new List<Task>();

            var asyncStart = DateTime.Now;
            tasks.Add(Task.WhenAll(Enumerable.Range(0, 10).Select(i =>
                ShowIndexAsync(i, asyncStart))));

            var start = DateTime.Now;
            tasks.Add(Task.WhenAll(Enumerable.Range(0, 10).Select(i =>
                ShowIndex(i, start))));

            await Task.WhenAll(tasks);

            Console.ReadLine();
        }


        static async Task ShowIndexAsync(int index, DateTime start)
        {
            Console.WriteLine("ShowIndexAsync: {0} ({1})",
                index, DateTime.Now - start);
            await Task.Delay(index * 100);
            Console.WriteLine("!ShowIndexAsync: {0} ({1})",
                index, DateTime.Now - start);
        }

        static Task ShowIndex(int index, DateTime start)
        {
            return Task.Factory.StartNew(() => {
                Console.WriteLine("ShowIndex: {0} ({1})",
                    index, DateTime.Now - start);
                Task.Delay(index * 100).Wait();
                Console.WriteLine("!ShowIndex: {0} ({1})",
                    index, DateTime.Now - start);
            });
        }
    }
}

因此,这会调用 ShowIndexAsync 10 次,然后调用 ShowIndex 10 次并等待它们完成。 ShowIndexAsync 是“与核心异步”,而 ShowIndex 不是,但它们都对任务进行操作。这里的阻塞操作是 Task.Delay,区别在于一个等待该任务,而另一个 .Wait() 则在任务内部进行。

您希望第一个队列(ShowIndexAsync)首先完成,但您是错误的。

ShowIndexAsync: 0 (00:00:00.0060000)
!ShowIndexAsync: 0 (00:00:00.0070000)
ShowIndexAsync: 1 (00:00:00.0080000)
ShowIndexAsync: 2 (00:00:00.0110000)
ShowIndexAsync: 3 (00:00:00.0110000)
ShowIndexAsync: 4 (00:00:00.0120000)
ShowIndexAsync: 5 (00:00:00.0130000)
ShowIndexAsync: 6 (00:00:00.0130000)
ShowIndexAsync: 7 (00:00:00.0140000)
ShowIndexAsync: 8 (00:00:00.0150000)
ShowIndexAsync: 9 (00:00:00.0150000)
ShowIndex: 0 (00:00:00.0020000)
!ShowIndex: 0 (00:00:00.0020000)
ShowIndex: 1 (00:00:00.0030000)
!ShowIndex: 1 (00:00:00.1100000)
ShowIndex: 2 (00:00:00.1100000)
!ShowIndex: 2 (00:00:00.3200000)
ShowIndex: 3 (00:00:00.3200000)
!ShowIndex: 3 (00:00:00.6220000)
ShowIndex: 4 (00:00:00.6220000)
!ShowIndex: 4 (00:00:01.0280000)
ShowIndex: 5 (00:00:01.0280000)
!ShowIndex: 5 (00:00:01.5420000)
ShowIndex: 6 (00:00:01.5420000)
!ShowIndex: 6 (00:00:02.1500000)
ShowIndex: 7 (00:00:02.1510000)
!ShowIndex: 7 (00:00:02.8650000)
ShowIndex: 8 (00:00:02.8650000)
!ShowIndex: 8 (00:00:03.6660000)
ShowIndex: 9 (00:00:03.6660000)
!ShowIndex: 9 (00:00:04.5780000)
!ShowIndexAsync: 1 (00:00:04.5950000)
!ShowIndexAsync: 2 (00:00:04.5960000)
!ShowIndexAsync: 3 (00:00:04.5970000)
!ShowIndexAsync: 4 (00:00:04.5970000)
!ShowIndexAsync: 5 (00:00:04.5980000)
!ShowIndexAsync: 6 (00:00:04.5990000)
!ShowIndexAsync: 7 (00:00:04.5990000)
!ShowIndexAsync: 8 (00:00:04.6000000)
!ShowIndexAsync: 9 (00:00:04.6010000)

为什么会发生这种事?

任务调度程序只会使用这么多的实际线程。 “await”编译为协作多任务状态机。如果您有未等待的阻塞操作,在此示例中Task.Delay(...).Wait(),但在我的问题中,正则表达式匹配,它不会合作并让任务调度程序正确管理任务。

如果我们将示例程序更改为:

    static async void MainAsync(string[] args)
    {
        var asyncStart = DateTime.Now;
        await Task.WhenAll(Enumerable.Range(0, 10).Select(i =>
            ShowIndexAsync(i, asyncStart)));

        var start = DateTime.Now;
        await Task.WhenAll(Enumerable.Range(0, 10).Select(i =>
            ShowIndex(i, start)));

        Console.ReadLine();
    }

然后我们的输出变为:

ShowIndexAsync: 0 (00:00:00.0050000)
!ShowIndexAsync: 0 (00:00:00.0050000)
ShowIndexAsync: 1 (00:00:00.0060000)
ShowIndexAsync: 2 (00:00:00.0080000)
ShowIndexAsync: 3 (00:00:00.0090000)
ShowIndexAsync: 4 (00:00:00.0090000)
ShowIndexAsync: 5 (00:00:00.0100000)
ShowIndexAsync: 6 (00:00:00.0110000)
ShowIndexAsync: 7 (00:00:00.0110000)
ShowIndexAsync: 8 (00:00:00.0120000)
ShowIndexAsync: 9 (00:00:00.0120000)
!ShowIndexAsync: 1 (00:00:00.1150000)
!ShowIndexAsync: 2 (00:00:00.2180000)
!ShowIndexAsync: 3 (00:00:00.3160000)
!ShowIndexAsync: 4 (00:00:00.4140000)
!ShowIndexAsync: 5 (00:00:00.5190000)
!ShowIndexAsync: 6 (00:00:00.6130000)
!ShowIndexAsync: 7 (00:00:00.7190000)
!ShowIndexAsync: 8 (00:00:00.8170000)
!ShowIndexAsync: 9 (00:00:00.9170000)
ShowIndex: 0 (00:00:00.0030000)
!ShowIndex: 0 (00:00:00.0040000)
ShowIndex: 3 (00:00:00.0060000)
ShowIndex: 4 (00:00:00.0090000)
ShowIndex: 2 (00:00:00.0100000)
ShowIndex: 1 (00:00:00.0100000)
ShowIndex: 5 (00:00:00.0130000)
ShowIndex: 6 (00:00:00.0130000)
ShowIndex: 7 (00:00:00.0150000)
ShowIndex: 8 (00:00:00.0180000)
!ShowIndex: 7 (00:00:00.7660000)
!ShowIndex: 6 (00:00:00.7660000)
ShowIndex: 9 (00:00:00.7660000)
!ShowIndex: 2 (00:00:00.7660000)
!ShowIndex: 5 (00:00:00.7660000)
!ShowIndex: 4 (00:00:00.7660000)
!ShowIndex: 3 (00:00:00.7660000)
!ShowIndex: 1 (00:00:00.7660000)
!ShowIndex: 8 (00:00:00.8210000)
!ShowIndex: 9 (00:00:01.6700000)

请注意,异步调用如何具有良好的均匀结束时间分布,但非异步代码却没有。任务调度程序被阻塞,因为它不会创建额外的实际线程,因为它期待合作。

我不希望它花费更少的CPU时间或类似的东西,但我的目标是使FindThings协作庄园中的多任务,即使其“与核心异步”。


正则表达式搜索是一个受 CPU 限制的操作,因此需要时间。您可以使用Task.Run将工作推到后台线程,从而保持 UI 响应,但这不会帮助他们更快地进行。

由于您的搜索已经是并行的,因此您可能无能为力。您可以尝试使用异步文件读取来减少线程池中阻塞线程的数量,但它可能不会产生巨大的效果。

您当前的代码正在调用ReadToEndAsync但它需要打开文件进行异步访问(即使用FileStream构造函数并通过传递显式请求异步文件句柄true为了isAsync参数或FileOptions.Asynchronous为了options范围)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C# 中是否存在异步正则表达式?它们对我的情况有帮助吗? 的相关文章

  • 是否可以从 C++ 应用程序调用 C# 应用程序?

    我是一名编程学生 现在我已经上了两门 C 课程 这个学期我将参加我的第一门 C 课程 出于好奇 是否可以从 C 应用程序调用 C 应用程序 如果是的话 是否还可以检查运行该程序的计算机是否具有 NET框架 我只是很好奇 我想如果可能的话 这
  • 无法将 std::min 传递给函数,std::min 的副本有效

    Passing std min函数无法编译 我复制了 libcpp 声明std min进入我的源文件并且它可以工作 std 版本有什么问题 clang 和 gcc 也会发生同样的情况 在 Godbolt 上测试 https godbolt
  • 我如何知道 C 程序的可执行文件是在前台还是后台运行?

    在我的 C 程序中 我想知道我的可执行文件是否像这样在前台运行 a out 或者像这样 a out 如果你是前台工作 getpgrp tcgetpgrp STDOUT FILENO or STDIN FILENO or STDERR FIL
  • Emacs 正则表达式:什么 \< 和 \> 可以做 \b 不能做的事情?

    正则表达式反斜杠 GNU Emacs 手册 http www gnu org software emacs manual html node emacs Regexp Backslash html说 lt 匹配单词的开头 gt 匹配单词末尾
  • 为什么需要数字后缀?

    C 语言 我确信还有其他语言 需要在数字文字末尾添加后缀 这些后缀指示文字的类型 例如 5m是一个小数 5f是一个浮点数 我的问题是 这些后缀真的有必要吗 或者是否可以从上下文中推断出文字的类型 例如 代码decimal d 5 0应该推断
  • 静态类与类的实例

    我有一个静态类 用于访问我的公共属性 整个应用程序的全局属性 和我在应用程序运行期间使用的方法 例如 我在静态类中设置了一些属性 并且在应用程序运行时我可以从属性中获取值 但我可以使用单例模式创建非静态类并以相同的方式使用它 问题 对于我的
  • 在 C# 中何时使用 ArrayList 而不是 array[]?

    我经常使用一个ArrayList而不是 正常 array 当我使用时 我感觉好像我在作弊 或懒惰 ArrayList 什么时候可以使用ArrayList在数组上 数组是强类型的 并且可以很好地用作参数 如果您知道集合的长度并且它是固定的 则
  • 使用 C# 中的 Google 地图 API 和 SSIS 包获取行驶距离

    更新 找到了谷歌距离矩阵并尝试相应地修改我的代码 我在这里收到无效参数错误 return new GeoLocation dstnc uri ToString catch return new GeoLocation 0 0 https 基
  • 用于连接 DataTable 上的动态列的动态 LINQ

    我目前遇到的情况不确定如何继续 我有两个从数据库填充的数据表 我还有一个可用的列名称列表 可用于将这两个数据表连接在一起 我希望编写一组 LINQ 查询 这些查询将 显示两个数据表中的行 内部联接 用于从一个数据表更新另一个数据表 显示一个
  • 时间:2019-03-17 标签:c++fstream并发访问

    如果从不同的进程 线程同时访问文件会发生什么 据我所知 没有锁定文件的标准方法 只有操作系统特定的功能 就我而言 文件将被经常读取而很少写入 现在如果A打开一个文件进行读取 ifstream 并开始读取块 和B打开相同的文件进行写入 ofs
  • ALTER TABLE ... ADD CONSTRAINT 失败时将事务回滚到保存点

    有没有办法在事务中添加检查约束and如果失败回滚到以前的保存点 而不是回滚整个事务 就我而言 当 ALTER TABLE ADD CONSTRAINT 命令失败时 事务无法回滚到保存点 尝试这样做会引发 InvalidOperationEx
  • 为什么 f(i = -1, i = -1) 是未定义的行为?

    我正在读关于违反评估顺序 http en cppreference com w cpp language eval order 他们举了一个令我困惑的例子 1 如果标量对象上的副作用相对于同一标量对象上的另一个副作用是无序的 则行为未定义
  • 从 NumPy 数组到 Mat 的 C++ 转换 (OpenCV)

    我正在围绕 ArUco 增强现实库 基于 OpenCV 编写一个薄包装器 我试图构建的界面非常简单 Python 将图像传递给 C 代码 C 代码检测标记并将其位置和其他信息作为字典元组返回给 Python 但是 我不知道如何在 Pytho
  • 如何在dll级别读取app.config? [复制]

    这个问题在这里已经有答案了 我在一个解决方案中有一个控制台应用程序项目和库项目 dll The 图书馆项目有 app config 文件 我在其中存储我在库中使用的一些键值对 控制台应用程序引用此 dll 我有另一个 app config
  • C 语言中的 Alpha 混合 2 RGBA 颜色[重复]

    这个问题在这里已经有答案了 可能的重复 如何快速进行阿尔法混合 https stackoverflow com questions 1102692 how to do alpha blend fast 对 2 个 RGBA 整数 颜色进行
  • Linq.Select() 中的嵌套表达式方法调用

    I use Select i gt new T 每次手动点击数据库后将我的实体对象转换为 DTO 对象 以下是一些示例实体和 DTOS 用户实体 public partial class User public int Id get set
  • Xamarin.Forms UWP 项目中标题栏和选项卡之间令人恼火的空白

    我几乎是新手Xamarin Forms我正在开发一个相当简单的跨平台应用程序 该应用程序在 Android 中显示得足够好 但在 UWP 中却出现了一个愚蠢的空白 该项目由一个 TabbedPage 组成 其中包含 4 个 Navigati
  • Bash 正则表达式——似乎无法匹配任何 \s \S \d \D \w \W 等

    我有一个脚本试图从 gparted 获取信息块 我的数据如下所示 Disk dev sda 42 9GB Sector size logical physical 512B 512B Partition Table msdos Number
  • 将 char 绑定到枚举类型

    我有一段与此非常相似的代码 class someclass public enum Section START MID END vector section Full void ex for int i 0 i section
  • 如何在c linux中收听特定接口上的广播?

    我目前可以通过执行以下操作来收听我编写的简单广播服务器 仅广播 hello int fd socket PF INET SOCK DGRAM 0 struct sockaddr in addr memset addr 0 sizeof ad

随机推荐