BeginInvoke copy parameter

Just try to learn Invoke/BeginInvoke, I encountered in that problem.

       // Update UI
       public void UpdateForm(string value) {
        txtLog.AppendText(value + "\r\n");
       }


       // Thread function
       private void readSocket() {
        string row = "";

        while (socket.Connected) {                
            row = socket.readLine();            

            if (IsControlValid(this))
                BeginInvoke((MethodInvoker)delegate { UpdateForm(String.Copy(row)); });                    

        }
    }

Using Invoke method my UI update with the correct text, instead if I use BegineInvoke I see wrong text, ie some text repeatedly a lot of time. I know that call

BeginInvoke((MethodInvoker)delegate { UpdateForm(row); });  

maybe "row" can be behavior like a shared variable rather than

BeginInvoke((MethodInvoker)delegate { UpdateForm(String.Copy(row)); });                    

I think that each BeginInvoke call create a "new" delegate, so using String.Copy must create another instance of string, but I see always wrong value (duplicates, ecc).

Where I'm wrong?

Jon Skeet
people
quotationmark

maybe "row" can be behavior like a shared variable rather than

Yes, the row variable is captured - so whenever it's read, it's the latest value that's read. You should put the variable declaration inside the loop:

while (socket.Connected) {                
    string row = socket.readLine();

    if (IsControlValid(this)) {
        // Removed String.Copy call, as it was pointless
        BeginInvoke((MethodInvoker)delegate { UpdateForm(row); });
    }
}

Now you'll have a different variable for each iteration of the loop, so you won't be overwriting the previous value in one thread while you're reading it in the delegate.

people

See more on this question at Stackoverflow