给出以下代码:
string injectedString = "Read string out of HttpContext";
Task.Factory.StartNew(() =>
{
MyClass myClass = new MyClass();
myClass.Method(injectedString);
}
这是将字符串传递给Task / Thread的最佳方法吗?
我对这种方法的担忧是:
这是在Asp.Net网络服务中,如果它很重要并且是一个火灾和忘记类型的线程,我不会等待任何类型的响应。
我的字符串实际上是从HttpContext
中读出来的,这是我以这种方式注入它的一个原因(Thread无法访问调用线程HtppContext
)< / p>
答案 0 :(得分:10)
您应该使用Task.Factory.StartNew(Action<object> action, object state)
重载将状态传递给新任务。
Task.Factory.StartNew((object myState) => {
var i = (int)myState;
//Do calculations...
var x = i + 10;
}, 10);
答案 1 :(得分:9)
您的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大小的引用重复指向字符串(仅限字符串文字..)
答案 2 :(得分:1)
如果您担心injectedString
可能会在myClass.Method(injectedString);
运行之前“收集垃圾”?
答案是否。您无需担心这一点,因为injectedString
在lambda
关闭时不再是局部变量。它将成为新编译器生成的类中的一个字段。
如果您担心垃圾收集器会在合适的时间收集它吗?
答案是是,当该类的实例超出范围且在托管代码中没有引用它时,它会执行。在Task
完成并且超出范围之后,肯定会发生这种情况。