我知道 .NET lambda 表达式可以捕获外部变量。 但是,我已经多次看到变量作为参数显式传递给 lambda 表达式,并且 .NET 库似乎也支持这种情况(例如 ThreadPool.QueueUserWorkItem)。
我的问题是这些捕获的限制是什么?实际在与创建它们的线程不同的线程上执行的 lambda(例如 ThreadPool.QueueUserWorkItem 或 Thread)或充当回调(即稍后调用)的 lambda 怎么样?
一般来说,什么时候应该依赖捕获变量,什么时候使用显式参数?例如:
public void DoStuff()
{
string message = GetMessage();
ThreadPool.QueueUserWorkItem(s => SendMessage(message)); // use captured variable
// -- OR --
ThreadPool.QueueUserWorkItem(s =>
{
string msg = (string)s;
SendMessage(msg);
}, message); // use explicit parameter
}
谢谢!
更新:修复了第二个 ThreadPool.QueueUserWorkItem 示例。
最佳答案
我认为在你的第一个例子中,你的意思是
QueueUserWorkItem( () => SendMessage(message) );
在你的第二项中,参数s
是从哪里来的?我想你的意思是
QueueUserWorkItem( s => {SendMessage((string)s);} , message );
现在,这两个功能等效,但是
第一种情况:参数
message
从范围复制 此DoStuff
方法并存储 直接在你的 lambda 表达式中 本身,作为一个闭包。 lambda 有 保留一份message
的副本。第二种情况:发送
message
到Queue
,队列保持 持有它(连同 lambda), 直到调用 lambda。这是 在运行时通过 lambda,到 lambda。
我认为第二种情况在编程上更灵活,因为它理论上允许您稍后在调用 lambda 之前更改 message
参数的值。然而,第一种方法更容易阅读并且更不易产生副作用。但在实践中,两者都有效。
关于c# - Lambda 表达式、捕获的变量和线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3900036/