如何将变量传递给另一个线程

时间:2010-10-19 14:36:34

标签: c# multithreading arguments

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();
    }
}
}

7 个答案:

答案 0 :(得分:4)

如果您想要使用您的呼叫序列“流动”某些数据,您还可以使用CallContextHere 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.LogicalSetData("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.LogicalGetData("time"));
        Console.Read(); 
    } 
  } 
} 

答案 1 :(得分:3)

Thread.Start存在一个重载,允许您传入参数。

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();
    }
}

答案 2 :(得分:1)

获得将变量传递给线程的相同效果的一种方法是创建您希望传递给线程的类型的类范围私有数据成员。在启动线程之前将此值设置为您想要的任何值。如果您有许多线程,则需要锁定此类范围的数据成员以防止意外值。或者,您可以使用.NET本机Mutex功能来控制对变量的访问。

例如(没有测试这个,只是在运行中写下来):

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();
    }
}
}

答案 3 :(得分:0)

如果您询问如何将参数传递给线程,请参阅:

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

答案 4 :(得分:0)

我不确定我是否正确理解您的问题,但以下MSDN文章展示了如何以您正在进行的方式(即通过ThreadStart和委托)将数据传递给线程:

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); 
    }
}

答案 5 :(得分:0)

我使用一个单独的worker类并在构造函数中填充成员变量,然后使用void方法作为我的委托使用私有成员变量:

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);
        }
    }

}

答案 6 :(得分:0)

我在vb2005中编写的一个简单的类集将允许轻松创建具有一到四个绑定参数和零个或一个未绑定参数的委托。复制/粘贴代码很乱,因为.net不支持可变参数泛型,但可以创建一个MethodInvoker,它会调用foo(bar,boz)来表示(vb.net语法,但方法是相同的C#):

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

将生成一个对象,其中包含Param1作为BarType,Param2作为BozType,而Action作为Action(BarType,BozType)。它会将这些字段设置为bar,boz和foo,并返回一个调用doIt的MethodInvoker,这个方法调用了Action(Param1,Param2)。如果我需要Action(整数),我会使用:

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

真的很光滑。 Lambdas避免使用剪切和粘贴库,但它们的内部实现类似。我读过Lambdas在编辑和继续时会造成困难;我知道我的方法没有。