将参数传递给Task.Factory.StartNew

给出以下代码:

string injectedString = "Read string out of HttpContext"; Task.Factory.StartNew(() => { MyClass myClass = new MyClass(); myClass.Method(injectedString); } 

这是将字符串传递给任务/线程的最佳方法吗?

我对这种方法的担忧是:

  • 垃圾收集器是否知道字符串何时脱离上下文并正确清理它?
  • 是否有更好的方法将依赖项注入到主线程中断开对象链接的任务?

这是在Asp.Net网络服务中,如果它很重要并且是一个火灾和忘记类型的线程,我不是在等待任何类型的响应。

我的字符串实际上是从HttpContext读出来的,这是我以这种方式注入它的一个原因(Thread无法访问调用线程HtppContext

您的lambda将被提升到编译器生成的类中。 injectedString变量将成为该类的字段。

因此,当生成的类超出范围(基本上在lambda的最后)时,它将被垃圾收集,并且GC决定执行集合。

回应你的评论:

没有重复。 编译器转为:

  string injectedString = "Read string out of HttpContext"; Task.Factory.StartNew(() => { MyClass myClass = new MyClass(); myClass.Method(injectedString); } 

进入这个:

 CompilerGeneratedClass c1 = new CompilerGeneratedClass(); c1.injectedString = "Read string out of HttpContext"; // call delegate here. 

还要记住:字符串是在CLR中实现的。 即使代码是重复的,字符串文字也会在池中实现。 您基本上只有一个本地WORD大小的引用重复指向字符串(仅限字符串文字..)

您应该使用Task.Factory.StartNew(Actionaction, object state)重载将状态传递给新任务。

 Task.Factory.StartNew((object myState) => { var i = (int)myState; //Do calculations... var x = i + 10; }, 10); 

如果你担心在myClass.Method(injectedString);之前myClass.Method(injectedString);可能是“垃圾收集” myClass.Method(injectedString); 跑?

答案是否定的 。 您不必担心这一点,因为在lambda关闭时, lambda不再是局部变量。 它将成为新编译器生成的类中的一个字段。

如果您担心垃圾收集器会在合适的时间收集它吗? 答案是肯定的 ,当该类的实例超出范围且在托管代码中没有引用它时,它将会执行。 在Task 完成并超出范围后,肯定会发生这种情况。