views:

104

answers:

8
using System;

using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace ConsoleApplication1
{
class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Taking data from Main Thread\n->");
        string message = Console.ReadLine();

        ThreadStart newThread = new ThreadStart(delegate { Write(message); });

        Thread myThread = new Thread(newThread);

    }

    public static void Write(string msg)
    {
        Console.WriteLine(msg);
        Console.Read();
    }
}
}
A: 

If you are asking how to pass parameters to threads, refer to this:

http://www.yoda.arachsys.com/csharp/threads/parameters.shtml

Brad
A: 

I am not sure if I understand your question correctly, but the following MSDN article shows how to pass data to a thread in the way that you are doing it (i.e., via ThreadStart and a delegate):

Passing data to thread

using System;
using System.Threading;

class Test
{
    static void Main() 
    {
        // To start a thread using a static thread procedure, use the
        // class name and method name when you create the ThreadStart
        // delegate. Beginning in version 2.0 of the .NET Framework,
        // it is not necessary to create a delegate explicitly. 
        // Specify the name of the method in the Thread constructor, 
        // and the compiler selects the correct delegate. For example:
        //
        // Thread newThread = new Thread(Work.DoWork);
        //
        ThreadStart threadDelegate = new ThreadStart(Work.DoWork);
        Thread newThread = new Thread(threadDelegate);
        newThread.Start();

        // To start a thread using an instance method for the thread 
        // procedure, use the instance variable and method name when 
        // you create the ThreadStart delegate. Beginning in version
        // 2.0 of the .NET Framework, the explicit delegate is not
        // required.
        //
        Work w = new Work();
        w.Data = 42;
        threadDelegate = new ThreadStart(w.DoMoreWork);
        newThread = new Thread(threadDelegate);
        newThread.Start();
    }
}

class Work 
{
    public static void DoWork() 
    {
        Console.WriteLine("Static thread procedure."); 
    }
    public int Data;
    public void DoMoreWork() 
    {
        Console.WriteLine("Instance thread procedure. Data={0}", Data); 
    }
}
Michael Goldshteyn
A: 

Precisely how you did it.

Pieter
A: 

I use a separate worker class and populate a member variable in the constructor, I then use a void method as my delegate that uses the private member variable:

using System;

using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Taking data from Main Thread\n->");
            string message = Console.ReadLine();
            WorkerClass workerClass = new WorkerClass(message);

            ThreadStart newThread = new ThreadStart(workerClass.DoWork);

            Thread myThread = new Thread(newThread);
            myThread.Start();
            Console.Read();

        }


    }

    internal class WorkerClass
    {
        private string _workerVariable = "";

        internal WorkerClass(string workerVariable)
        {
            _workerVariable = workerVariable;
        }

        internal void DoWork()
        {
            Console.WriteLine(_workerVariable);
        }
    }

}
Peter Walke
+1  A: 

One way to get the same effect of passing a variable to a thread is to make a classwide private data member of the type you wish to pass to the thread. Set this value to whatever you want before you start the thread. If you have many threads, you will need to put a lock on this classwide data member to prevent unexpected values. Or you can use .NET native Mutex functionality to control access to the variable.

For example (didn't test this, just wrote it up on the fly):

using System;

using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace ConsoleApplication1
{
class Program
{
    private string threadVariable;

    static void Main(string[] args)
    {
        Console.WriteLine("Taking data from Main Thread\n->");
        string message = Console.ReadLine();

        threadVariable = "stuff";

        Thread myThread = new Thread(Write);
        Thread.IsBackground = true;
        Thread.Start();
    }

    public static void Write()
    {
        Console.WriteLine(stuff);
        Console.Read();
    }
}
}
kmarks2
A: 

You can also use a the CallContext if you have some data that you want to "flow" some data with your call sequence. Here is a good blog posting about LogicalCallContext from Jeff Richter.

using System;  
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading; 

namespace ConsoleApplication1 
{ 
  class Program 
  { 
    static void Main(string[] args) 
    { 
        Console.WriteLine("Taking data from Main Thread\n->"); 
        string message = Console.ReadLine(); 

        //Put something into the CallContext
        CallContext.SetData("time", DateTime.Now);

        ThreadStart newThread = new ThreadStart(delegate { Write(message); }); 

        Thread myThread = new Thread(newThread); 

    } 

    public static void Write(string msg) 
    { 
        Console.WriteLine(msg); 
        //Get it back out of the CallContext
        Console.WriteLine(CallContext.GetData("time"));
        Console.Read(); 
    } 
  } 
} 
wageoghe
A: 

One handy set of classes I wrote up in vb2005 would allow the easy creation of a delegate with one to four bound arguments and zero or one unbound arguments. A huge mess of copy/paste code, since .net doesn't support variadic generics, but one could create a MethodInvoker which would call foo(bar,boz) by saying (vb.net syntax, but the approach would be the same in C#):

  theMethodInvoker = InvMaker.NewInv(addressof foo, bar, boz)
  theMethodInvoker() ' Calls foo(bar,boz)

which would generate an object containing fields Param1 as BarType, Param2 as BozType, and theAction as Action(of BarType, BozType). It would set those fields to bar, boz, and foo, and return a MethodInvoker which would call doIt, a method which called theAction(Param1, Param2). If I needed an Action(of Integer), I would use:

  theMethodInvoker = ActionMaker(of Integer).NewInv(addressof foo, bar, boz)
  theMethodInvoker(9) ' Calls foo(9,bar,boz)

Really slick. Lambdas avoid the need for a cut-and-paste library, but their internal implementation is similar. I've read that Lambdas cause difficulty with edit-and-continue; I know my method does not.

supercat
A: 

There is an overload to Thread.Start that lets you pass in a parameter.

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Taking data from Main Thread\n->");
        string message = Console.ReadLine();  

        Thread myThread = new Thread(Write);
        myThread.Start(message);

    }

    public static void Write(object obj)
    {
        string msg = (string)obj;
        Console.WriteLine(msg);
        Console.Read();
    }
}
bufferz