views:

238

answers:

10

I want to pass a function that takes a parameter to the ThreadStart Constructor in C#. But, it seems that this is not possible, as I get a syntax error it I try to do something like this

Thread t1 = new Thread(new ThreadStart(func1(obj1));

where obj1 is an object of type List<string> (say).

If I want a thread to execute this function that takes in an object as a parameter, and I plan to create 2 such threads simultaneously with different parameter values what is the best method to achieve this?

+4  A: 

If you're using .NET 3.5 or higher, one option is to use a lambda for this:

var myThread = new System.Threading.Thread(() => func1(obj1)); 
Mark Rushakoff
Thanks a lot!!!
assassin
+2  A: 

Try this:

var bar = 0.0;
Thread t = new Thread(() => 
    {
        Foo(bar);
    });
t.IsBackground = true;
t.Start();

Or in your case:

Object obj1 = new Object();
Thread t = new Thread(() => 
    {
        func1(obj1);
    });
t.IsBackground = true;
t.Start();
Lirik
Thanks a lot!!!
assassin
+4  A: 

You can start a new thread like this:

Thread thread = new Thread(delegate() {
    // Code here.
});
thread.Start();

Inside the anonymous method you have access to the variables that were in scope when the delegate was created.

Mark Byers
+3  A: 

You need ParametrizedThreadStart to pass a parameter to a thread.

Thread t1 = new Thread(new ParametrizedThreadStart(func1);
t1.Start(obj1);
Thomas
Thanks a lot.. this method works.. however, the definition for func1 in this case will have to bevoid func1(object state)and cannot be void func1(List<string> obj1)why is this the case?
assassin
That's how the `ParametrizedThreadStart` delegate type is defined. You'll have to cast the `object` back to `List<string>` inside `func1`.
Thomas
+2  A: 

Edit Assassin had trouble getting this code to work, so I have included a complete example console app at the end of this post.



{ // some code
  Thread t1 = new Thread(MyThreadStart);
  t1.Start(theList);
}

void MyThreadStart(object state)
{
  List<string> theList = (List<string>)state;
  //..
}


This is my edit: Below is a complete console app -- the technique really does work:


using System;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            System.Threading.Thread t = new System.Threading.Thread(MyThreadStart);
            t.Start("Hello");
            System.Console.ReadLine();
        }


        static void MyThreadStart(object state)
        {
            System.Console.WriteLine((string)state);
        }
    }
}


JMarsch
This doesn't work.. i tried it... the ParametrizedThreadStart method suggested by Thomas works.
assassin
@assassin I assure you, it does work. I have edited my entry to include a console app that you can paste directly into Visual Studio and run. This syntax has worked since .Net 2.0, and if you replace the "new Thread(MyThreadStart)" with "new Thread(new delegate
JMarsch
A: 

See ParameterizedThreadStart

KMan
+1  A: 

Is this the effect you're looking for?

        static void Main(string[] args)
    {
        var list = new List<string>(){
            "a","b","c"
        };

        Thread t1 = new Thread(new ParameterizedThreadStart(DoWork));

        t1.Start(list);

        Console.ReadLine();

    }

    public static void DoWork(object stuff)
    {
        foreach (var item in stuff as List<string>)
        {
            Console.WriteLine(item);
        }
    }
Ragoczy
+1  A: 
static void func1(object parameter)
{
   // Do stuff here.
}

static void Main(string[] args)
{
  List<string> obj1 = new List<string>();
  Thread t1 = new Thread(func1);
  t1.Start(obj1);
}

It's using a new delegate in .Net 2.0 called ParameterizedThreadStart. You can read about it here.

TheCodeMonk
A: 

Do you absolutely need to use a Thread object? Or are you just looking for multithreaded processing to happen? A more "modern" approach would be to use an asynchronous delegate as such:

private delegate void FuncDelegate(object obj1);
.
.
.
FuncDelegate func = func1;
IAsyncResult result = func.BeginInvoke(obj1, Completed, func);

// do other stuff
.
.
.

private void Completed(IAsyncResult result)
{
    ((FuncDelegate)result.AsyncState).EndInvoke(result);

    // do other cleanup
}

An even more "modern" method would be to use Tasks in the .NET 4 TPL.

Jesse C. Slicer
A: 

You can declare class of yours which contains the object you want to pass to the new thread. Then you should specify member function - not just function as argument of the ThreadStart delegate's constructor:

class MyClass

{

private List m_List;

public MyClass(List a_List){m_List=a_List;}

void ThreadFunction() {... use m_List;}

}

...

List MyList=new List();

...

MyClass ThreadParam=new MyClass(MyList);

MyThread= new Thread(new ThreadStart(ThreadParam.ThreadFunction));

MyThread.Start();

ThreadParam object becomes thread's argument.

ThreadFunction can use it via this keyword.

irakl