How to pass a ref parameter inside lambda expression? - Thread issue

泪湿孤枕 提交于 2021-01-27 21:26:54

问题


I have a method to be called.

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

To call it in a thread

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

Of course we get an error.

Cannot use ref or out parameter 'ChanResource' inside an anonymous method, lambda expression, or query expression

How to fix it?


回答1:


You can't use ref. See this very same question.

That being said, the reason you mentioned (The object is big and used often, I don't want to pass it in value type) is not valid.

You won't pass your parameter as value if you remove ref. There won't be any performance/memory gain to use ref here. See value vs reference.




回答2:


Why that error?

The scope of the parameters of an anonymous method is the anonymous-method-block.

(Emphasis mine)

lambda expressions are essentially the same as anonymous method.

As per the doc, the scope of the parameters is limited to its block.

But ref and out are outside the scope and hence that error. I recommend you not to use ref, as parameters are by default passed by value, and in case of reference type, the value of the reference is passed.

You can modify the parameter directly to reflect that change.




回答3:


Instead:

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

You should do:

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



回答4:


You don't have to pass this object as a reference if you are not recreating it in your method. If you are recreating it however than your ref would make sense:

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

Creating an object by ref causes the caller to be created as a new object.

You cannot send ref in lambda expressions because of the closure environment. C# compiles the anonymous expressions in runtime. If you try to send a ref to your closured code, then the compiler has to find a way to reach out your ref object which doesn't make sense. Here you can check the closures: http://en.wikipedia.org/wiki/Closure_(computer_science)




回答5:


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));

The only problem is that your procedure now edits field inside passed object, not the actual variable, so you must check that field.



来源:https://stackoverflow.com/questions/23476543/how-to-pass-a-ref-parameter-inside-lambda-expression-thread-issue

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!