2010-10-19 1 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

Gibt es hier eine Frage? – Jonathan

+1

Lol, 'rate die Frage Frage' –

+0

Nun, die 'Nachricht'-Variable wird bereits an die 'Write'-Methode übergeben (die auf einem anderen Thread ausgeführt wird) also was willst du mehr? –

Antwort

4

Sie auch die CallContext verwenden können, wenn Sie einige Daten, die Sie einige Daten zu „fließen“ wollen mit Ihrer Anruffolge. 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 ("Zeit") gibt null innerhalb des Threads zurück. – Rauhotz

0

Ich bin nicht sicher, ob ich Ihre Frage richtig verstanden habe, aber der folgende MSDN-Artikel zeigt, wie die Daten auf dem Weg zu einem Thread zu übergeben, die Sie es tun (dh über Threadstart und Delegierten):

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

ich eine separate Arbeiter-Klasse verwenden und eine Membervariable in dem Konstruktor zu füllen, habe ich dann eine Lücke Methode als meinen Delegaten verwenden, die die privaten Variable verwendet:

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

Eine Möglichkeit, den gleichen Effekt zu erzielen Das Übergeben einer Variablen an einen Thread besteht darin, ein klassenweites privates Datenelement des Typs zu erstellen, den Sie an den Thread übergeben möchten. Setzen Sie diesen Wert auf den gewünschten Wert, bevor Sie den Thread starten. Wenn Sie viele Threads haben, müssen Sie dieses klassenweite Datenelement sperren, um unerwartete Werte zu vermeiden. Oder Sie können die native Mutex-Funktionalität von .NET verwenden, um den Zugriff auf die Variable zu steuern.

Zum Beispiel (habe dies nicht testen, schrieb es nur on the fly up):

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

Ein handliches Set von Klassen schrieb ich in VB2005 würde die einfache Erstellung eines Delegierten mit 3.59 gebundenen Argumente und null oder einem ungebundenen Argumente ermöglichen. Ein riesiges Durcheinander von Copy/Paste-Code, da .net keine variadischen Generics unterstützt, aber man könnte einen MethodInvoker erzeugen, der foo (bar, boz) sagt, indem er sagt (vb.net syntax, aber der Ansatz wäre der gleiche) C#):

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

, die ein Objekt enthält Felder Param1 als BarType, Param2 als BozType und theAction als Aktion erzeugen würde (von BarType, BozType). Es würde diese Felder auf bar, boz und foo setzen und einen MethodInvoker zurückgeben, der doIt aufrufen würde, eine Methode, die theAction (Param1, Param2) aufgerufen hat. Wenn ich eine Aktion (von Integer) benötige, würde ich folgendes verwenden:

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

Wirklich glatt. Lambdas vermeiden die Notwendigkeit einer Ausschneiden-und-Einfügen-Bibliothek, aber ihre interne Implementierung ist ähnlich. Ich habe gelesen, dass Lambdas Schwierigkeiten mit Edit-and-Continue verursachen; Ich weiß, dass meine Methode nicht funktioniert.

3

Thread.Start enthält eine Überladung, mit der Sie einen Parameter übergeben können.

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