Parallel.For循环使用NHunspell和c#进行拼写检查

时间:2013-08-17 19:47:02

标签: c# task-parallel-library nhunspell

我有一个字符串列表,如果我按顺序使用NHunspell进行拼写检查,那么一切正常;但如果我对List使用Parallel.For循环,则应用程序在中间停止工作(某些地址违规错误)

public static bool IsSpellingRight(string inputword, byte[] frDic, byte[] frAff, byte[] enDic, byte[] enAff)
{
    if (inputword.Length != 0)
    {
        bool correct;
        if (IsEnglish(inputword))
        {
            using (var hunspell = new Hunspell(enAff, enDic))
            {
                correct = hunspell.Spell(inputword);
            }
        }
        else
        {
            using (var hunspell = new Hunspell(frAff, frDic))
            {
                correct = hunspell.Spell(inputword);
            }
        }
        return correct ;
    }

    return false;
}

编辑:

var tokenSource = new CancellationTokenSource();
CancellationToken ct = tokenSource.Token;

var poptions = new ParallelOptions();

// Keep one core/CPU free...
poptions.MaxDegreeOfParallelism = Environment.ProcessorCount - 1;
Task task = Task.Factory.StartNew(delegate
{
    Parallel.For(0, total, poptions, i =>
    {
        if (words[i] != "")
        {
            _totalWords++;

            if (IsSpellingRight(words[i],dictFileBytes,
                affFileBytes,dictFileBytesE,affFileBytesE))
            {
                // do something   

            }
            else
            {
                BeginInvoke((Action) (() =>
                {
                    //do something on UI thread
                }));
            }
        }
    });
}, tokenSource.Token);

task.ContinueWith((t) => BeginInvoke((Action) (() =>
{
    MessaageBox.Show("Done");
})));

2 个答案:

答案 0 :(得分:1)

好的,现在我可以看到一个潜在的问题。在行

_totalWords++;

你正在递增一个值,我(我想)在循环之外的某个地方被声明。使用锁定机制。

编辑: 此外,您可以使用Interlocked.Increment(ref val);,这比简单锁定更快。

EDIT2: 以下是我在评论中描述的锁定应该与您遇到的问题类似:

static object Locker = new object();    //anywhere in the class

//then in your method
if (inputword.Length != 0)
{
   bool correct;
   bool isEnglish;
   lock(Locker) {isEnglish = IsEnglish(inputword);}
   if(isEnglish)
   {
       //..do your stuff
   }
    //rest of your function
}

答案 1 :(得分:1)

我认为你应该忘记你的并行循环实现正确的事情。

您是否知道此代码加载并构造字典:

    using (var hunspell = new Hunspell(enAff, enDic))
    {
        correct = hunspell.Spell(inputword);
    }

您正在使用您的代码一遍又一遍地加载和构建字典。这非常慢!加载您的字典并检查所有单词,然后处理它。并且不要并行执行此操作,因为Hunspell对象不是线程安全的。

<强> Pseodocode:

Hunspell hunspell = null;
try
{
    hunspell = new Hunspell(enAff, enDic)

    for( ... )
    {
      hunspell.Spell(inputword[i]);
    }
    }
}
finally
{
    if( hunspell != null ) hunspell.Dispose();
}

如果您需要检查大量并行的单词,请阅读本文: http://www.codeproject.com/Articles/43769/Spell-Check-Hyphenation-and-Thesaurus-for-NET-with