2010-10-19 39 views
6
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

¿Hay alguna pregunta aquí? – Jonathan

+1

Lol, 'adivinar la cuestión pregunta' –

+0

Bueno, la variable 'mensaje' se está pasando al método' Write' ya (que se ejecutará en otro hilo) entonces, ¿qué más quieres? –

Respuesta

4

También se puede utilizar una la CallContext si tiene algunos datos que desea "flujo" de algunos datos con tu secuencia de llamadas. 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") devuelve nulo dentro del hilo. – Rauhotz

0

No estoy seguro de si he entendido bien su pregunta, pero el siguiente artículo de MSDN muestra cómo pasar datos a un hilo en la forma en que lo está haciendo (es decir, a través de ThreadStart y un delegado):

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

utilizo una clase de trabajo independiente y rellenar una variable miembro en el constructor, que luego usar un método vacío como mi delegado que utiliza la variable miembro privada:

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

} 
1

Una forma de obtener el mismo efecto de pasar una variable a un hilo es hacer un miembro de datos privados de toda la clase del tipo que desea pasar al hilo. Establezca este valor en lo que quiera antes de iniciar el hilo. Si tiene muchos hilos, deberá poner un candado en este miembro de datos de clase para evitar valores inesperados. O puede usar la funcionalidad Mutex nativa de .NET para controlar el acceso a la variable.

Por ejemplo (no probar esto, acabo de escribir arriba sobre la marcha):

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

Un práctico conjunto de clases que escribió en VB2005 permitiría la fácil creación de un delegado de uno a cuatro argumentos encuadernados y cero o uno argumentos no unidos. Un gran lío de código copiar/pegar, ya que .net no admite genéricos varicos, pero se podría crear un MethodInvoker que llamaría a foo (bar, boz) diciendo (vb.net sintaxis, pero el enfoque sería el mismo en C#):

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

lo que generaría un objeto que contiene campos Param1 como BarType, Param2 como BozType, y theaction como acción (de BarType, BozType). Establecería esos campos para bar, boz y foo, y devolvería un MethodInvoker que llamaría doIt, un método que llamaba Action (Param1, Param2). Si necesitaba una Acción (de Entero), usaría:

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

Realmente resbaladizo. Lambdas evita la necesidad de una biblioteca de cortar y pegar, pero su implementación interna es similar. He leído que Lambdas causa dificultades con edit-and-continue; Sé que mi método no.

3

Hay una sobrecarga en Thread.Start que le permite pasar un parámetro.

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