在lambda express --thread问题中传递ref参数

时间:2014-05-05 15:43:53

标签: c# lambda

我有一个方法可以调用。

public void RecordConversation(ref ChannelResource cr)
{
    VoiceResource RecordResource = TServer.GetVoiceResource();
    RecordResource.MaximumTime = 6000;
    RecordResource.MaximumSilence = 6000;
    RecordResource.TerminationDigits = "";
}

在线程中调用它

Thread recordThread = new Thread(() => RecordConversation(ref ChanResource));
recordThread.Start();

当然我们收到错误。

  

不能在匿名方法,lambda表达式或查询表达式中使用ref或out参数'ChanResource'

如何解决?

6 个答案:

答案 0 :(得分:4)

为什么会出错?

  

匿名方法的参数范围   的匿名方法块

强调我的

lambda表达式与匿名方法基本相同。

根据文档,参数的范围仅限于其块。

但是refout超出了范围,因此出现了错误。我建议您不要使用ref,因为参数默认按值传递,如果是引用类型,则传递引用值。

您可以直接修改参数以反映该更改。

答案 1 :(得分:3)

您无法使用ref。请参阅this very same question

话虽如此,你提到的原因(对象很大且经常使用,我不想以值类型传递它)是无效的。

如果您移除ref ,则无法将参数作为值传递。在这里使用ref不会有任何性能/内存增益。 请参阅value vs reference

答案 2 :(得分:0)

相反:

Thread recordThread = new Thread(() => RecordConversation(ref ChanResource));
recordThread.Start();

你应该这样做:

Thread recordThread = new Thread(() => {
    VoiceResource RecordResource = TServer.GetVoiceResource();
    RecordResource.MaximumTime = 6000;
    RecordResource.MaximumSilence = 6000;
    RecordResource.TerminationDigits = "";
});
recordThread.Start();

答案 3 :(得分:0)

如果不在方法中重新创建此对象,则不必将此对象作为参考传递。如果你正在重新创建它,那么你的参考将是有道理的:

public void RecordConversation(ref ChannelResource cr)
{
    cr = new ChannelResource();
    VoiceResource RecordResource = TServer.GetVoiceResource();
    RecordResource.MaximumTime = 6000;
    RecordResource.MaximumSilence = 6000;
    RecordResource.TerminationDigits = "";
}

通过ref创建对象会导致调用者被创建为新对象。

由于闭包环境,您无法在lambda表达式中发送ref。 C#在运行时编译匿名表达式。如果您尝试将ref发送到已关闭的代码,那么编译器必须找到一种方法来触及您的ref对象,这是没有意义的。在这里,您可以查看闭包:http://en.wikipedia.org/wiki/Closure_(computer_science)

答案 4 :(得分:0)

public class ThreadParams
{
    public ChannelResource ChanResource;
    public ThreadParams(ChannelResource chanResource) {
        ChanResource = chanResource; }
}

public void ThreadProc(Object obj)
{
    RecordConversation(ref ((ThreadParams)obj).ChanResource);
}

Thread recordThread = new Thread(ThreadProc);
recordThread.Start(new ThreadParams(ChanResource));

唯一的问题是你的程序现在编辑传递对象内的字段,而不是实际变量,因此你必须检查该字段。

答案 5 :(得分:-2)

我不打算回答你的问题。我只会提供一些有助于澄清问题的代码:

class Foo
{
    public string Bar{get;set;}
}

//somewhere else
void Main()
{
    var foo = new Foo();
    foo.Bar = "monkey";
    ChangeFoo(foo);
    //is it monkey or giraffe? 
    //according to your understanding, still monkey. Actually giraffe.
    Console.WriteLine(foo.Bar); 
}
void ChangeFoo(Foo someFoo)
{
    //someFoo is a reference to foo above, not a value copy
    foo.Bar = "giraffe";
}

我建议您运行此代码,请注意缺少任何ref关键字,并在您的问题的上下文中考虑其含义,坦率地说,这是一个非问题。因此,我没有回答。