SoFunction
Updated on 2025-03-06

C# implements three examples of parameters to multi-threaded C#

This article describes three ways of C# implementing parameters to multi-threads. Share it for your reference, as follows:

From "C# Advanced Programming", I learned that there are two ways to pass parameters to threads. One is to use the Thread constructor with ParameterizedThreadStart delegate parameters. The other is to create a custom class and define the thread's method as an instance method, so that the instance's data can be initialized and the thread can be started.

Method 1: Use ParameterizedThreadStart Delegate

If the ParameterizedThreadStart delegate is used, the thread's entry must have an object-type parameter and the return type is void. Let’s look at the following example:

using System;
using ;
namespace ThreadWithParameters
{
  class Program
  {
    static void Main(string[] args)
    {
      string hello = "hello world";
      //This can also be abbreviated as Thread thread = new Thread(ThreadMainWithParameters);      //But in order to let everyone know that the ParameterizedThreadStart commission is used here, there is no abbreviation      Thread thread = new Thread(new ParameterizedThreadStart(ThreadMainWithParameters));
      (hello);
      ();
    }
    static void ThreadMainWithParameters(object obj)
    {
      string str = obj as string;
      if(!(str))
        ("Running in a thread,received: {0}", str);
    }
  }
}

What's a little troublesome here is that the parameters in the ThreadMainWithParameters method must be of object type, and we need to perform type conversion. Why must the parameters be of object type? You can find out by looking at the declaration of ParameterizedThreadStart delegation.

public delegate void ParameterizedThreadStart(object obj);   // Statement of ParameterizedThreadStart delegation

Method 2: Create a custom class

Define a class, define the required fields, and define the thread's main method as an instance method of the class. It is not very clear, so look at the actual example.

using System;
using ;
namespace ThreadWithParameters
{
  public class MyThread
  {
    private string data;
    public MyThread(string data)
    {
       = data;
    }
    public void ThreadMain()
    {
      ("Running in a thread,data: {0}", data);
    }
  }
  class Program
  {
    static void Main(string[] args)
    {
      MyThread myThread = new MyThread("hello world");
      Thread thread = new Thread();
      ();
      ();
    }
  }
}

I am not very satisfied with this method. I can’t create a new class once I encounter a time-consuming method. . .

So what better way is to not cast or create a new class?

Let me introduce a method I found accidentally. I don’t remember where I have seen it. It’s a sin. .

Method 3: Use anonymous method

using System;
using ;
namespace ThreadWithParameters
{
  class Program
  {
    static void Main(string[] args)
    {
      string hello = "hello world";
      //If you write Thread thread = new Thread(ThreadMainWithParameters(hello)); this form will report an error during compilation      Thread thread = new Thread(() => ThreadMainWithParameters(hello));
      ();
      ();
    }
    static void ThreadMainWithParameters(string str)
    {
       ("Running in a thread,received: {0}", str);
    }
  }
}

Wow, you will find that it runs successfully without type casting or new class.

But why does this method work? According to the prompt from @South month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month month

The following is the IL code decompiled by the third main method:

.method private hidebysig static void Main(string[] args) cil managed
{
  .entrypoint
  // Code size 51 (0x33)  .maxstack 3
  .locals init ([0] class [mscorlib] thread,
       [1] class /'<>c__DisplayClass1' 'CS$<>8__locals2')
  IL_0000: newobj   instance void /'<>c__DisplayClass1'::.ctor()
  IL_0005: stloc.1
  IL_0006: nop
  IL_0007: ldloc.1
  IL_0008: ldstr   "hello world"
  IL_000d: stfld   string /'<>c__DisplayClass1'::hello
  IL_0012: ldloc.1
  IL_0013: ldftn   instance void /'<>c__DisplayClass1'::'<Main>b__0'()
  IL_0019: newobj   instance void [mscorlib]::.ctor(object, native int)
  IL_001e: newobj   instance void [mscorlib]::.ctor(class [mscorlib])
  IL_0023: stloc.0
  IL_0024: ldloc.0
  IL_0025: callvirt  instance void [mscorlib]::Start()
  IL_002a: nop
  IL_002b: call    int32 [mscorlib]::Read()
  IL_0030: pop
  IL_0031: nop
  IL_0032: ret
} // end of method Program::Main

Let's look at the second way of IL code:

.method private hidebysig static void Main(string[] args) cil managed
{
  .entrypoint
  // Code size 44 (0x2c)  .maxstack 3
  .locals init ([0] class  myThread,
       [1] class [mscorlib] thread)
  IL_0000: nop
  IL_0001: ldstr   "hello world"
  IL_0006: newobj   instance void ::.ctor(string)
  IL_000b: stloc.0
  IL_000c: ldloc.0
  IL_000d: ldftn   instance void ::ThreadMain()
  IL_0013: newobj   instance void [mscorlib]::.ctor(object, native int)
  IL_0018: newobj   instance void [mscorlib]::.ctor(class [mscorlib])
  IL_001d: stloc.1
  IL_001e: ldloc.1
  IL_001f: callvirt  instance void [mscorlib]::Start()
  IL_0024: nop
  IL_0025: call    int32 [mscorlib]::Read()
  IL_002a: pop
  IL_002b: ret
} // end of method Program::Main

Comparing the two-end code, we can find that both have a newobj. The purpose of this sentence is to initialize an instance of a class. The third method is to generate a class by the compiler: c__DisplayClass1

IL_0000: newobj   instance void /'<>c__DisplayClass1'::.ctor()
IL_0006: newobj   instance void ::.ctor(string)

Note: Simplicity is not necessarily a good thing, and anonymous methods can easily cause unobserved errors

I hope this article will be helpful to everyone's C# programming.