Question

I have a list of string and if I run spell checking using NHunspell in sequential manner then everything works fine; but if I use Parallel.For loop against the List the application stops working in the middle( some address violation error )

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;
}

Edit:

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");
})));
Was it helpful?

Solution

I think you should forget about your parallel loop implement the things right.

Are you aware of the fact that this code loads and constructs the dictionary:

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

Your are loading and construction the dictionary over and over again with your code. This is awfully slow! Load Your dictionary once and check all words, then dispose it. And don't do this in parallel because Hunspell objects are not thread safe.

Pseodocode:

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

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

If you need to check words massive in parallel consider to read this article: http://www.codeproject.com/Articles/43769/Spell-Check-Hyphenation-and-Thesaurus-for-NET-with

OTHER TIPS

Ok, now I can see a potential problem. In line

_totalWords++;

you're incrementing a value, that (I suppose) is declared somewhere outside the loop. Use locking mechanism.

edit: Also, you could use Interlocked.Increment(ref val);, which would be faster, than simple locking.

edit2: Here's how the locking I described in comment should look like for the problem you encounter:

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
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top