Click here to Skip to main content
15,867,750 members
Please Sign up or sign in to vote.
5.00/5 (3 votes)
See more:
Hi all!
I want to pass reference parameter to thread.
Code snippet:
C#
private void Start(ref TcpClient handler)
{
  ClientThread = new Thread(delegate() { HandleClientComm(ref handler); });
  ClientThread.Start( handler);
}

But it writes to me:
"Cannot use ref or out parameter inside an annonymous method, lambda expression, query expression"

Or how to keep reference(not value) to the variable?

Who could help me?
Posted
Updated 9-Feb-11 19:43pm
v4
Comments
JF2015 10-Feb-11 0:45am    
Edited to add code formatting.
Sergey Alexandrovich Kryukov 10-Feb-11 1:06am    
Thank you for interesting question. Is is not very simple, my 5.
Please see my answer -- it covers all you may need.
Please ask further questions
--SA

Good question. First to think about: do you really need to? There is much better method: to wrap a thread and pass this. After that, the thread accesses anything in the class. Isn't that nice?

C#
internal class ThreadWrapper {

    internal ThreadWrapper(/*..*/) {
        /* pass whatever needed from out side */
        Thread = new System.Threading.Thread(Body); //don't tell my it is illegal!
    } //ThreadWrapper

    internal void Start() { this.Thread.Start(); }
    internal void Abort() { this.Thread.Abort(); }

    //and so on...

    void Body() {
        if (this.SomeByRefParameter == null) //can read
            this.SomeByRefParameter = new System.Text.StringBuilder(); //can modify
        //why? because this member is non-static, "this" parameter is used
        //...
    } //Body

    object SomeByRefParameter;
    System.Threading.Thread Thread;

} //class ThreadWrapper


Can you see what's going on? We managed to run non-static (instance) method as a thread start point. As this is an instance method, Body has hidden parameter called this; it is used to pass an instance of the ThreadWrapper. As we have the instance, we can access any members of this instance (shown on example of SomeByRefParameter). You can have other methods of the wrapper accessible from outside and pass any parameter using by value of by reference methods. Don't forget to use synchronization primitives, such as lock.

Don't be afraid; this method of starting thread is not very well documented, but it is much more reliable than starting point with parameter because type casting is not required.

—SA
 
Share this answer
 
Comments
JF2015 10-Feb-11 1:18am    
Good alternative solution.
Sergey Alexandrovich Kryukov 10-Feb-11 1:25am    
Thank you very much, but how it is alternative? I mean, there is no way to pass by ref except this one, in my opinion. If you know another way, that way will be alternative...
--SA
Albin Abel 15-Apr-11 15:36pm    
Right solution. My 5
Sergey Alexandrovich Kryukov 15-Apr-11 15:55pm    
Thank you, Albin.
By the way, it renders parametrized thread start pretty much useless, as it requires type cast for limited functionality.
--SA
NuttingCDEF 4-May-11 16:20pm    
Good method - 5.
The problem is that you are attempting to pass a ref variable to an anonymous method. Here is why that is a problem:
C#
Start(ref handler);
handler.DoSomething();
// handler could change here.
handler.DoSomething();

If you pass in an instance by reference to your function and that function passes that reference variable to an anonymous method, that anonymous method could then be executed in a different thread, which would cause the variable reference to change at an undetermined time (such as when the comment in the above code is reached). Since the passing by "ref" is only supposed to change the variable reference when you return from the method call, this functionality is invalid. Here is one way you might get around that (uses a temporary variable):
C#
private void Start(ref TcpClient handler)
{
  var handler2 = handler;
  ClientThread = new Thread(delegate() { HandleClientComm(ref handler2); });
  ClientThread.Start();
  // ClientThread.Join();   // Uncomment this line to ensure HandleClientComm has finished running.
  handler = handler2; // handler2 may or may not have changed by now.
}

That may cause unintended side effects, but at least your code will compile.
 
Share this answer
 
v2
Comments
IllidanS4 15-Jun-15 14:13pm    
More problematic than having a variable changed at undetermined time is the lifetime of the variable. When the method ends, the stack frame will be released, and so the reference would be invalid in the created thread, which is inacceptable, of course.
Pass Ref Parameter[^] will give you an idea.
 
Share this answer
 
Comments
Sergey Alexandrovich Kryukov 10-Feb-11 1:04am    
Sorry, this is quite irrelevant to threads. Even though it can help with understanding of by ref, OP probably already understand it.
--SA

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900