Threading issues

I want to do some stuff in my app that is time consuming but which does not have an impact on the actual game. Therefore I am trying to use a thread to run that stuff separately. Here is how I create my thread:

Thread thread = new Thread(() => WriteCheckpointTextFile (myFileName, checkpoint));
thread.Start();

Here is the code I am running in WriteCheckpointTextFile:

void WriteCheckpointTextFile (string fileName, Checkpoint checkpoint)
{
			string checkpointToText = "";
			checkpointToText += CheckpointDataNames.nextMarker + Environment.NewLine;
			checkpointToText += checkpoint.nextMarker + Environment.NewLine;
			checkpointToText += "%" + Environment.NewLine;

			checkpointToText += CheckpointDataNames.difficulty + Environment.NewLine;
			checkpointToText += checkpoint.difficulty.ToString () + Environment.NewLine;
			checkpointToText += "%" + Environment.NewLine;

			checkpointToText += CheckpointDataNames.musicObject + Environment.NewLine;
			checkpointToText += checkpoint.musicObject + Environment.NewLine;
			checkpointToText += "%" + Environment.NewLine;

			checkpointToText += CheckpointDataNames.gameTimePassed + Environment.NewLine;
			checkpointToText += checkpoint.gameTimePassed.ToString () + Environment.NewLine;
			checkpointToText += "%" + Environment.NewLine;

			checkpointToText += CheckpointDataNames.storedStats + Environment.NewLine;
			checkpointToText += EndRaceDataString (checkpoint.storedStats);
			checkpointToText += "%" + Environment.NewLine;

			checkpointToText += CheckpointDataNames.pursuers + Environment.NewLine;
			foreach (PursuerData p in checkpoint.pursuers) {
					checkpointToText += p.pursuerName + "," + p.pursuerNextMarker + "," + p.pursuerPosition.x.ToString () + "," + p.pursuerPosition.y.ToString () + "," + p.pursuerPosition.z.ToString () + Environment.NewLine;

			}
			checkpointToText += "%" + Environment.NewLine;
			#if !UNITY_WEBPLAYER

			System.IO.File.WriteAllText (fileName, checkpointToText);

			#endif
			Debug.Log("Finished writing text to file");
}

Now for some reason that last debug doesn’t always get printed and my file is not always written. What could be causing this?

With the information you provided in the comment:

I have managed to find the issue,
which is caused by a “Collection was
modified; enumeration operation may
not execute.”

It seems that what’s happening is that you’re modifying an enumeration while enumerating it.

Looking at your code, you are iterating over “checkpoint.pursuers”:

foreach (PursuerData p in checkpoint.pursuers)
{
    // ...
}

This object is passed as data to this thread, and is probably being updated on another thread.

Well, the reason could be a race condition which might terminate your thread. You don’t use any syncronisation and it seems you directly work on game data structures. Even read-access can cause a race-condition due to caching in the CPU.

Also make sure you don’t start two of those threads at the same time / overlapping since that would require both threads to have an open write-handle to your file which isn’t possible and would cause an exception.

Debugging a threaded application is very hard since there are hundreds of things which could possibly go wrong. That’s why you should always take precaution and syncronise everything that might cause a problem. If you are inexperienced in threading it might be better to not use threads or read some books on threading :wink:

Ouch, lets forget first about Threading for a second and do this:

This code is slow because you create hundred of strings, please use StringBuilder

Usage old.

string checkpointToText = "";
checkpointToText += CheckpointDataNames.nextMarker + Environment.NewLine;

New

StringBuilder checkpointToText = new StringBuilder();
checkpointToText.AppendLine(CheckpointDataNames.nextMarker);

Also this is very very bad

checkpointToText += p.pursuerName + "," + p.pursuerNextMarker + "," + p.pursuerPosition.x.ToString () + "," + p.pursuerPosition.y.ToString () + "," + p.pursuerPosition.z.ToString () + Environment.NewLine;

Use string.Format to do such stuff

If you are done with filling the StringBuilder then just use checkpointToText.ToString();