在MultiThreaded环境中使用Regex

时间:2017-02-27 16:29:13

标签: c# regex multithreading

我有一个构造函数,它在名为Regex的类中使用static readonlyRegexLib个对象(主要是因为这个项目使用了大量需要的Regex个模式在各处使用。

当用户向应用程序添加一些文件时,将为每个文件调用此构造函数一次(跨多个线程异步运行)。我已经附加了构造函数在下面调用的相关函数。

private void GetSymbolsFromLines()
{
    for (int i = 0; i < Lines.Length; i++)
    {
        string line = Lines[i];
        if (RegexLib.InstString.IsMatch(line))
        {
            int instString = i;
            int userdataString = 0;
            for (int j = i; j < Lines.Length; j++)
            {
                if (RegexLib.UserdataString.IsMatch(Lines[j]))
                {
                    userdataString = j;
                    break;
                }
                else if (Lines[j].Contains("userdata"))
                {
                    break;
                }
            }

            if (userdataString != 0)
            {
                _symbols.Add(new Symbol(RegexLib.InstString.Match(Lines[instString]), 
                    RegexLib.UserdataString.Match(Lines[userdataString])));
            }
        }
    }
}

Regex个对象与这些对象非常相似,并且已使用Regex Hero进行了测试。

    public static readonly Regex AliasFromUserdata = new Regex(@"text_alias=(?<AliasName>\w+).*?value=(?<AliasValue>(.*?))\^(?=(?:text_alias|\""))");
    public static readonly Regex UpdateFromUserdata = new Regex("FOX_VAR=.*?attr=(?<AttributeType>.+?)\\^(?<AttributePropertyString>.*?)\\^(?:(?=(?:FOX_VAR|END_FOXV)))");

出于某种原因,Regex的使用似乎在这个多线程环境中引起了一些问题,并且挖掘documentation显示这可能是因为:

  

但是,Regex返回的结果对象(Match和MatchCollection)应该在一个线程上使用。

所以我的问题是,出于组织原因,是否有一种简单的方法可以使用Regex跨越多个线程,同时在库类中构建它们?

我能想到的唯一可能的解决方案是将Regex声明移近使用是在使用前克隆对象,但这看起来可能很慢。

作为参考,这里是在4个不同线程上并发运行的Worker Function。

 private void FoxFileConvWorker(ConcurrentQueue<string> queue,QueueProgressData qpd)
    {
        string[] extensions = {".fdf", ".m1", ".g"};
        while (!queue.IsEmpty)
        {
            string file;
            if (queue.TryDequeue(out file))
            {
                if (extensions.Any(extension => Path.GetExtension(file) == extension))
                {
                    try
                    {
                        _jobGraphics.Add(new Graphic(file));
                        IncrementProgress(qpd);
                    }
                    catch (Exception e)
                    {
                        ThreadSafeControlMethods.SetText(qpd.LblStatus, "Non-Fatal Error");
                        WriteLog(e, $"Creating Graphic DOM for {file}");
#if DEBUG
                        throw;
#endif
                    }

                }
            }
        }
    }

1 个答案:

答案 0 :(得分:2)

您可以修改静态Regex类吗?如果是这样,您可以使用Factory而不是静态属性:

default-time-zone = YourTimezone

这样,你就不会在线程之间共享你的正则表达式了。

您也可以使用一些依赖注入,但这意味着您的代码中会进行大量的重构。