2013-08-17 38 views
0

我有一个字符串的列表,如果我运行拼写检查使用NHunspell顺序方式,然后一切工作正常;但如果我使用的Parallel.For循环对列表中的应用程序停止运行在中间(一些地址冲突错误)Parallel.For循环拼写检查使用NHunspell和C#

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

哪里列表和你谈论的循环?更有可能的是,当你从多个线程使用列表时,你只是搞砸了一些东西。 – Tarec

+0

该列表只是一个由RichTextBox文本构建的单词的标记化列表 – jeff

+0

我不熟悉Hunspell类,但只需键入'correct = true;'或'false',运行它,然后查看是否问题在于你的方法或你的Parallel.For循环。在你粘贴的代码中我没有看到任何错误,除非Hunspell是一个单例 - 那么它显然意味着你不能以这种方式使用它。 – Tarec

回答

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

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 
} 
+0

我删除它,仍然是同样的问题。只有当我在布尔IsEnglish(字符串)中设置true或false时,程序运行良好。那么我现在该做什么? – jeff

+0

仍然是同样的问题 – jeff

+0

我认为这个问题可能在多个线程试图改变的变量'correct'中。我是对的,因为我遵循你的指令来锁定IsEnglish方法,但同样的问题 – jeff