Created
August 15, 2010 12:59
-
-
Save joshpeterson/525467 to your computer and use it in GitHub Desktop.
This code queues some work for a background thread, then waits for that work to complete.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// #FixMyCode | |
// This code queues some work for a background thread, then waits for that work to complete. | |
// Can you make it more correct, more elegant, faster, or just plain better? If so, please do! | |
// Fork this Gist and tweet me the result @joshuampeterson. | |
using System; | |
using System.Collections.Generic; | |
using System.Threading; | |
namespace WaitForBackgroundThread | |
{ | |
class Program | |
{ | |
private static int sum; | |
static void Main(string[] args) | |
{ | |
AutoResetEvent stopBackgroundThread = new AutoResetEvent(false); | |
Queue<WorkerInformation> queue = new Queue<WorkerInformation>(); | |
object queueLock = new object(); | |
int gaussianSum = (1000 * 1001)/2; | |
BackgroundThread consumer = new BackgroundThread(stopBackgroundThread, queue, queueLock); | |
SentinelArgs sentinelArgs = new SentinelArgs(); | |
lock (queueLock) | |
{ | |
for (int i = 1; i <= 1000; ++i) | |
{ | |
queue.Enqueue(new WorkerInformation(AddToSum, null, new AddToSumArgs(i))); | |
} | |
queue.Enqueue(new WorkerInformation(SignalSentinel, null, sentinelArgs)); | |
} | |
sentinelArgs.Sentinel.WaitOne(); | |
Console.WriteLine("Gauss's sum: {0}", gaussianSum); | |
Console.WriteLine("Background thread's sum: {0}", sum); | |
Console.WriteLine("They {0}!", gaussianSum == sum ? "match" : "do not match"); | |
stopBackgroundThread.Set(); | |
} | |
class AddToSumArgs : EventArgs | |
{ | |
private int numberToAdd; | |
public AddToSumArgs(int numberToAdd) | |
{ | |
this.numberToAdd = numberToAdd; | |
} | |
public int NumberToAdd { get { return this.numberToAdd; } } | |
} | |
private static void AddToSum(object sender, EventArgs arguments) | |
{ | |
sum += ((AddToSumArgs)arguments).NumberToAdd; | |
} | |
class SentinelArgs : EventArgs | |
{ | |
private AutoResetEvent sentinel = new AutoResetEvent(false); | |
public AutoResetEvent Sentinel { get { return this.sentinel; } } | |
} | |
private static void SignalSentinel(object sender, EventArgs arguments) | |
{ | |
((SentinelArgs)arguments).Sentinel.Set(); | |
} | |
delegate void Worker(object sender, EventArgs arguments); | |
class WorkerInformation | |
{ | |
private Worker worker; | |
private object sender; | |
private EventArgs arguments; | |
public WorkerInformation(Worker worker, object sender, EventArgs arguments) | |
{ | |
this.worker = worker; | |
this.sender = sender; | |
this.arguments = arguments; | |
} | |
public Worker Worker { get { return this.worker; } } | |
public object Sender { get { return this.sender; } } | |
public EventArgs Arguments { get { return this.arguments; } } | |
} | |
class BackgroundThread | |
{ | |
private AutoResetEvent stopBackgroundThread; | |
private Queue<WorkerInformation> queue; | |
private object queueLock; | |
public BackgroundThread(AutoResetEvent stopBackgroundThread, Queue<WorkerInformation> queue, | |
object queueLock) | |
{ | |
this.stopBackgroundThread = stopBackgroundThread; | |
this.queue = queue; | |
this.queueLock = queueLock; | |
Thread consumer = new Thread(this.Run); | |
consumer.Start(); | |
} | |
private void Run() | |
{ | |
while (!this.stopBackgroundThread.WaitOne(10)) | |
{ | |
WorkerInformation workerInformation = null; | |
lock (this.queueLock) | |
{ | |
if (this.queue.Count > 0) | |
{ | |
workerInformation = this.queue.Dequeue(); | |
} | |
} | |
if (workerInformation != null) | |
{ | |
workerInformation.Worker(workerInformation.Sender, workerInformation.Arguments); | |
} | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment