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

问题描述:

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

这里有问题吗? – Jonathan 2010-10-19 14:39:34

+1

哈哈,'猜猜问题问题' – 2010-10-19 14:40:31

+0

那么,'message'变量已经被传递给了'Write'方法(它将在另一个线程上执行),那么你还想要什么? – 2010-10-19 14:41:45

您也可以使用该CallContext如果你有想要“流”的一些数据的一些数据与您的通话顺序。 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.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(); 
    } 
    } 
} 
+0

CallContext.GetData(“time”)在线程内返回null。 – Rauhotz 2013-07-11 08:42:11

如果你问如何传递参数给线程,请参考本:

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

我不知道如果我正确地理解你的问题,但下面的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); 
    } 
} 

我使用一个单独的工人阶级,并在构造函数中填充的成员变量,然后我用一个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); 
     } 
    } 

} 

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

例如(没有测试这一点,只是写起来就飞):

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

一个方便的类集我VB2005写了将允许轻松创建一个委托一至四个绑定参数和零个或一个未绑定的参数。一大堆的复制/粘贴代码,因为.net不支持可变泛型,但是可以创建一个MethodInvoker,它会通过说(vb.net语法)来调用foo(bar,boz),但是这种方法在C#):

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

这将产生包含字段参数1为杆型,参数2为BozType的对象,并且作为theAction行动(杆型的,BozType)。它会将这些字段设置为bar,boz和foo,并返回一个称为doIt的MethodInvoker,该方法称为Action(参数1,参数2)。如果我需要动作(整数),我会用:

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

真的很漂亮。 Lambdas避免了对剪切和粘贴库的需求,但它们的内部实现类似。我读过Lambdas导致编辑和继续的困难;我知道我的方法没有。

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