0

I would like to pass a parameter to a method when I start it in a thread.

Also I want to do this in the context of a for loop for k=0 until k=10, for example.

Additionally I want each thread to be independent of each other. So far I have this:

for (int k = 0; k < 3; k++)
{
new Thread(() => Method2(list[k])).Start();
}

Where Method2 is supposed to do some processing, and is defined as follows(the body is unimportant, it basically creates and writes to a file):

public static void Method2(string SYM)

Somehow when I run the code, I do have three threads created, but the parameter passed to each thread seems to be only the list[2] parameter for all three. I expected each thread to have list[0] list[1] list[3] as parameters respectively.

1 Answers1

1

I think a better solution to this problem would be to use Parallel.ForEach.

static void Main( string[ ] _ )
{
    var list = new List<string> { "Value1", "Value2", "Value3" };
    Parallel.ForEach( list, value => Method2( value ) );
}

Here is another solution using Task's (setting and forgetting).

static void Main( string[ ] _ )
{
    var list = new List<string> { "Value1", "Value2", "Value3" };            
    for ( int i = 0; i < list.Count; i++ )
    {
        var index = i;
        // Set and forget.
        Task.Run( ( ) => Method2( list[ index ] ) );                                
    }
}

And here is another solution using Task's but this time you await for each of the Task's to complete.

static async Task Main( string[ ] _ )
{
    var list = new List<string> { "Value1", "Value2", "Value3" };
    var tasks = new List<Task>( list.Count );
    for ( int i = 0; i < list.Count; i++ )
    {
        var index = i;
        // Set and forget.
        tasks.Add( Task.Run( ( ) => Method2( list[ index ] ) ) ); 
    }

    await Task.WhenAll( tasks );
}

If you don't like that and want to stick with your solution then you can capture the i variable locally in the for loop.

for ( int i = 0; i < list.Count; i++ )
{
    var index = i;
    new Thread( ( ) => Method2( list[ index ] ) ).Start( );
}

Each Thread will have its own copy of the index variable, as opposed to each Thread sharing a reference to the i variable (which is what you're currently doing).

Your for loop is finishing before the first Thread has started; so when one of the Thread's finally starts it sees the last value that i was set to (in your case 3).

If you don't believe me run the below code.

static void Main( string[ ] _ )
{       
    for ( int i = 0; i < 3; i++ )
    {
        new Thread( ( ) => Console.WriteLine( $"{i}" ) ).Start( );
        Thread.Sleep( 1500 );
    }            
    Console.ReadLine( );
 }

You should see the values, 0, 1, 2 printed to the console. Now, run this code (and note that I removed the Thread.Sleep:

static void Main( string[ ] _ )
{       
    for ( int i = 0; i < 3; i++ )
    {
        new Thread( ( ) => Console.WriteLine( $"{i}" ) ).Start( );
    }            
    Console.ReadLine( );
}

You should see the values, 3, 3, 3 printed to the console.

WBuck
  • 5,162
  • 2
  • 25
  • 36