0

文字列のリストがあり、NHunspell を使用して順番にスペル チェックを実行すると、すべて正常に動作します。しかし、リストに対して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");
})));
4

2 に答える 2

1

並列ループを正しく実装することを忘れるべきだと思います。

このコードがディクショナリをロードして構築するという事実を認識していますか?

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

コードを使用して辞書を何度も読み込んで構築しています。これは非常に遅いです!あなたの辞書を一度読み込んで、すべての単語をチェックしてから、破棄してください。また、Hunspell オブジェクトはスレッド セーフではないため、これを並行して実行しないでください。

疑似コード:

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

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

大量の単語を並行してチェックする必要がある場合は、この記事を読むことを検討して ください。

于 2013-08-20T07:38:03.720 に答える
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
}
于 2013-08-17T20:26:41.060 に答える