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