C#警惕匿名方法造成的变量共享实例分析

2019-12-26 14:11:13于丽

解决问题

找到了问题所在,解决起来自然轻而易举:

 

 
  1. private class WrapperClass  { 
  2. private List<Item> m_items;  public WrapperClass(List<Item> items) 
  3. {  this.m_items = items; 
  4. }  public void WaitCallback(object o) 
  5. {  DataContext db = new DataContext(); 
  6. db.Items.InsertAllOnSubmit(this.m_items);  db.SubmitChanges(); 
  7. }  } 
  8. static void Process()  { 
  9. List<Item> batchItems = new List<Item>();  foreach (var item in ...) 
  10. {  batchItems.Add(item); 
  11. if (batchItems.Count > 1000)  { 
  12. ThreadPool.QueueUserWorkItem(  new WrapperClass(batchItems).WaitCallback); 
  13. batchItems = new List<Item>();  } 
  14. }  } 

这里我们明确地准备一个封装类,用它来保留我们需要提交的数据。而每次提交时则使用保留好的数据,自然不会发生不该有的“数据共享”,从而避免了错误的发生1。

总结

匿名方法是强大的,但是也会造成一些令人难以察觉的陷阱。对于使用匿名方法创建的委托,如果不会立即同步执行,并且其中使用了方法的局部变量,那么您就需要对其留个心眼了。因为此时“局部变量”事实上已经由编译器转变成一个自动类的实例上的Field字段,而这个字段将被当前方法和委托对象共享。如果您在创建了委托对象之后还会修改共享的“局部变量”,那么请再三确认这样做符合您的意图,而不会造成问题。