I like the idea of the JobData class, but there is already an answer demonstrating this, and the fact that you work with file paths gives you another possible advantage. Some characters are not valid in the file path, so you can choose one to use as a delimiter. The advantage here is that the queue type remains a string, so you do not have to modify any of the existing asynchronous codes. Here you can see a list of reserved path characters:
http://en.wikipedia.org/wiki/Filename#Reserved_characters_and_words
For our purposes, I will use the percent symbol (%). Then you can change your code as follows, and nothing else needs to be changed:
const int startingTTL = 100; const string delimiter = "%"; while(true) { String[] path = queue.pop().Split(delimiter.ToCharArray()); int ttl = path.Length > 1?--int.Parse(path[1]):startingTTL; if(process(path[0])) { Console.WriteLine("Good!"); } else if (ttl > 0) { queue.pushback(string.Format("{0}{1}{2}", path[0], delimiter,ttl)); } else { Console.WriteLine("TTL expired for path: {0}" path[0]); } }
Again, from a pure architecture point of view, a class with two properties is the best design ... but from a practical point of view, YAGNI : this parameter means that you can avoid returning and changing other asynchronous code that is queued. This code still needs to know only about strings and will work with this unmodified.
One more thing. I want to note that this is a rather complicated cycle, prone to run away with the processor core. Also, if it is a .Net queue type, and your hard loop is ahead of your asynchronous releases, to free the queue, you will throw an exception that will exit the while (true) block. You can solve both problems with the code as follows:
while(true) { try { String[] path = queue.pop().Split(delimiter.ToCharArray()); int ttl = path.Length > 1?--int.Parse(path[1]):startingTTL; if(process(path[0])) { Console.WriteLine("Good!"); } else if (ttl > 0) { queue.pushback(string.Format("{0}{1}{2}", path[0], delimiter,ttl)); } else { Console.WriteLine("TTL expired for path: {0}" path[0]); } } catch(InvalidOperationException ex) { //Queue.Dequeue throws InvalidOperation if the queue is empty... sleep for a bit before trying again Thread.Sleep(100); } }
Joel Coehoorn
source share