C#线程/锁定混乱

我有以下代码:

var items = new List {"1", "2", "3"}; // 200 items foreach(var item in items) { ThreadPool.QueueUserWorkItem((DoWork), item); } private void DoWork(object obj) { lock(this) { using(var sw = File.AppendText(@"C:\somepath.txt") { sw.WriteLine(obj); } } } 

由于线程,出于某种原因,我得到了写入文件的200个项目的随机数。 60或127或有时只有3.如果我删除ThreadPool并只在原始foreach循环内写入,则所有200个项目都会成功写入。

不知道为什么会这样?

谢谢你的帮助。

关于ThreadPool MSDN文档中的以下注释说明了这一切:

托管线程池中的线程是后台线程。 也就是说,它们的IsBackground属性是真的。 这意味着在所有前台线程退出后, ThreadPool线程不会保持应用程序运行

您的应用程序只是在线程完成运行之前退出(通过到达Main末尾)。

这是我所暗示的简单版本。 它使用单个事件并且不进行轮询或旋转,并且它被编写为可重用,并且允许同时允许多个工作集。 如果对调试更方便,可以将lambda表达式考虑在内。

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

短而甜的怎么样?

  static int wrkThreads = 0; static readonly EventWaitHandle exit = new ManualResetEvent(false); static readonly object syncLock = new object(); static void Main( string[] items ) { wrkThreads = items.Length; foreach ( var item in items ) ThreadPool.QueueUserWorkItem(( DoWork ), item); exit.WaitOne(); } static void DoWork( object obj ) { lock ( syncLock ) { /* Do your file work here */ } if ( Interlocked.Decrement(ref wrkThreads) == 0 ) exit.Set(); }