I have the following code:
var items = new List {\"1\", \"2\", \"3\"}; // 200 items
foreach(var item in items) {
ThreadPool.QueueUserWorkItem
This is a simple version of what I was alluding to. It uses a single event and does not poll or spin, and it's written so as to be reusable as well as allowing multiple work sets at the same time. The lambda expressions could be factored out, if that's more convenient for debugging.
class Program
{
static void Main(string[] args)
{
var items = new string[] { "1", "2", "3", "300" };
using (var outfile = File.AppendText("file.txt"))
{
using (var ws = new WorkSet(x =>
{ lock (outfile) outfile.WriteLine(x); }))
foreach (var item in items)
ws.Process(item);
}
}
public class WorkSet : IDisposable
{
#region Interface
public WorkSet(Action action)
{ _action = action; }
public void Process(T item)
{
Interlocked.Increment(ref _workItems);
ThreadPool.QueueUserWorkItem(o =>
{ try { _action((T)o); } finally { Done(); } }, item);
}
#endregion
#region Advanced
public bool Done()
{
if (Interlocked.Decrement(ref _workItems) != 0)
return false;
_finished.Set();
return true;
}
public ManualResetEvent Finished
{ get { return _finished; } }
#endregion
#region IDisposable
public void Dispose()
{
Done();
_finished.WaitOne();
}
#endregion
#region Fields
readonly Action _action;
readonly ManualResetEvent _finished = new ManualResetEvent(false);
int _workItems = 1;
#endregion
}
}