-2

how can I force the task to use the first value and not the second value. This is a simpler example of code that has become a problem for me.

        static void Main(string[] args)
        {            
           string testString = "1 value";
           Task.Factory.StartNew(() => PrintStr(testString));
           testString = "2 value";
           Console.ReadLine();
        }

        static void PrintStr(string str)
        {
            Console.WriteLine(str);
        }

In response I get "2 value"

The problem is that I need to pass a string to the task, after which this string will be changed and I cannot guarantee. that the task will receive the correct information.

I have a collection of posts, for each post I create a task and I need to pass the html markup in a string variable. For each step of the loop, this variable will change, and therefore I cannot be sure that the task will receive the correct data. Sample code:

foreach(var uid in uids) // collection of messages
{
  message = imapClient.Inbox.GetMessage(uid);
  var htmlData = message.HtmlBody.ToString();
  tasks.Add(Task.Factory.StartNew(() => someHandle(htmlData));
  
}

void someHandle(string data)
{
 //some code to handle the message 
}
lolmax78
  • 7
  • 1
  • 1
    Just to be clear, when you say you get "2 value", that's just one of 3 possible results: "2 value", "1 value" and a straight crash with an access violation exception are all possible outcomes of your code. – Blindy Nov 09 '20 at 18:59
  • You can't pass string non-atomically as it is reference type... https://stackoverflow.com/questions/11745440/what-operations-are-atomic-in-c – Alexei Levenkov Nov 09 '20 at 19:18
  • The variable is being captured by the delegate, so if it's used by the delegate after its value is changed, you get the new value. You need to use a copy of the value. See duplicate. – Peter Duniho Nov 15 '20 at 03:50

1 Answers1

1

Make a copy of the value to send. This has nothing to do with atomicity unless you make it (as you're trying in your example).

    static void Main(string[] args)
    {            
       string testString = "1 value";
       string testStringCopy = testString;
       Task.Factory.StartNew(() => PrintStr(testStringCopy));
       testString = "2 value";
       Console.ReadLine();
    }

    static void PrintStr(string str)
    {
        Console.WriteLine(str);
    }
Blindy
  • 65,249
  • 10
  • 91
  • 131
  • Just to emphasize (for the sake of the OP and other readers): this is creating a copy of the *variable* - it doesn't duplicate the *string itself*, and doesn't need to (because strings are immutable, unless you do bad things). With "captured variables" (lexical closures), variables have personality :) – Marc Gravell Nov 09 '20 at 20:12