private struct ThreadWorkBlock {
public readonly int StartingIndex;
public readonly int Count;
public ThreadWorkBlock(int startingIndex, int count) {
StartingIndex = startingIndex;
Count = count;
}
}
private static void CalculateWordCounts() {
wordList = GetWordList();
curseWords = GetCurseWords();
currentWordIndex = 0;
wordCountDict = new Dictionary<string, int>();
Thread threadA = new Thread(ThreadDoWork);
Thread threadB = new Thread(ThreadDoWork);
Thread threadC = new Thread(ThreadDoWork);
Thread threadD = new Thread(ThreadDoWork);
int numWords = wordList.Count;
int quarterOfWords = numWords / 4;
threadA.Start(new ThreadWorkBlock(quarterOfWords * 0, quarterOfWords));
threadB.Start(new ThreadWorkBlock(quarterOfWords * 1, quarterOfWords));
threadC.Start(new ThreadWorkBlock(quarterOfWords * 2, quarterOfWords));
threadD.Start(new ThreadWorkBlock(quarterOfWords * 3, numWords - quarterOfWords * 3));
threadA.Join();
threadB.Join();
threadC.Join();
threadD.Join();
}
private static void ThreadDoWork(object threadStartParameter) {
ThreadWorkBlock localWorkBlock = (ThreadWorkBlock) threadStartParameter;
Dictionary<string, int> localWordCountDict = new Dictionary<string, int>();
for (int i = localWorkBlock.StartingIndex; i < localWorkBlock.StartingIndex + localWorkBlock.Count; ++i) {
string thisWord = wordList[i].ToUpper().Replace("-", String.Empty).Replace("'", String.Empty).Trim();
bool firstLocalOccurrenceOfWord = !localWordCountDict.ContainsKey(thisWord);
if (firstLocalOccurrenceOfWord) localWordCountDict.Add(thisWord, 1);
else localWordCountDict[thisWord] = localWordCountDict[thisWord] + 1;
}
lock (wordCountCalculatorSyncObj) {
foreach (var kvp in localWordCountDict) {
bool firstGlobalOccurrenceOfWord = !wordCountDict.ContainsKey(kvp.Key);
if (firstGlobalOccurrenceOfWord) wordCountDict.Add(kvp.Key, kvp.Value);
else wordCountDict[kvp.Key] += kvp.Value;
}
}
}
Code snippet taken from "Common Multithreading Mistakes in C# - II: Unnecessary Contention".