2009-09-04 3 views
5

Wie ruft man eine Funktion auf, die zwei Parameter mit Threading in C# aufnimmt? Ich habe StartDNIThread (string storeID, string queryObject) von einem anderen function.I zu nennen haben die beiden values.Both sind StringEinfädeln in C#

Antwort

6
ThreadStart threadStart = delegate{StartDNIThread(string storeID, string queryObject);}; 
Thread thread = new Thread(threadStart); 
thread.Start(); 

Oder mit Lambda-Ausdrücke:

ThreadStart threadStart =() => StartDNIThread(string storeID, string queryObject); 
Thread thread = new Thread(threadStart); 
thread.Start(); 
+0

Ich erhalte den folgenden Fehler Eine nicht behandelte Ausnahme vom Typ 'System.NullReferenceException' aufgetreten in App_Code.g2edzdox.dll Weitere Informationen: Objektverweis nicht auf eine Instanz eines Objekts festgelegt. – Janmejay

8

Ihre Optionen übergeben werden:

  • die Parameter in einer neuen Klasse kapseln, und legen Sie die Methode fest, die für den Delegaten in dieser Klasse verwendet werden soll.
  • Verwenden Sie anonyme Funktionen (anonyme Methoden oder Lambda-Ausdrücke), um das Gleiche automatisch mit erfassten Variablen zu tun.

Letzteres ist natürlich einfacher. Sie haben nicht gezeigt, was Sie mit dem Faden tun, aber Sie könnten wie etwas tun:

string storeID = "..."; 
string queryObject = "..."; 

Thread t = new Thread(() => StartDNIThread(storeID, queryObject)); 
t.Start(); 

Beachten Sie, dass, weil die Variablen erfasst werden, sollten Sie nicht die Werte bis ändern, nachdem Sie das wissen Thread hat tatsächlich begonnen. Sie können nur durch die anonyme Funktion unter Verwendung von erfassten Variablen dieses Problem umgehen:

string storeID = "..."; 
string queryObject = "..."; 

string storeIDCopy = storeID; 
string queryObjectCopy = queryObject; 
Thread t = new Thread(() => StartDNIThread(storeIDCopy, queryObjectCopy)); 
t.Start(); 
// You can now change storeID and queryObject freely 

Dies ist besonders wichtig, wenn Sie etwas in einer Schleife tun, wie die Schleifenvariablen selbst ändern. Zum Beispiel:

foreach (string storeID in stores) 
{ 
    string storeIDCopy = storeID; 
    Thread t = new Thread(() => StartDNIThread(storeIDCopy, queryObject)); 
    t.Start(); 
} 

Wenn Sie den Thread-Pool oder auf andere Weise Fäden Start verwenden, ist das Muster im Grunde das gleiche.

+0

Upvote für Lambda-Ausdrücke. – Rap

2

Mit dem Threadpool:

string str1 = "str1"; 
string str2 = "str2"; 
ThreadPool.QueueUserWorkItem(state => 
          { 
           Console.WriteLine("{0}:{1}", str1, str2); 
          }); 

Wenn Sie einige alternative Thread-Verarbeitung beteiligt eine UI tun wollen, sind Sie am besten die BackgroundWorker verwenden.

1

Es gibt einen ParameterizedThreadStart Delegierten, die Sie nutzen könnten. Dieser Delegat erfordert eine Methode, die ein Argument (des Tyoe-Objekts) verwendet. In der Tat könnten Sie einen benutzerdefinierten Typ (Klasse oder Struktur) verwenden, der die 2 Variablen enthält, die Sie an den ParameterizedThreadStart übergeben möchten.

So:

Thread t = new Thread (new ParameterizedThreadStart (DoWork)); 
t.Start(new MyType(storeId, queryObject)); 

Aber in solchen Situationen, ziehe ich es in einer anderen Art und Weise zu tun. Ich bevorzuge es, einen benutzerdefinierten 'Task'-Typ zu erstellen, der all diese Dinge abstrahiert. So:

public class Task 
{ 

    private readonly int _storeId; 
    private readonly string _queryObject; 

    public Task(int storeId, string queryObject) 
    { 
     _storeId = storeId; 
     _queryObject = queryObject; 
    } 

    public void Start() 
    { 
     Thread t = new Thread (new ThreadStart(DoWork)); 
     t.Start(); 
    } 

    private void DoWork() 
    { 
     // Do your thing here. 
    } 

} 
0

Ich neige dazu, eine Task-Objekt so etwas wie die folgenden

class myClass 
{ 
    public void CallingCode() 
    { 
     ProcessRequest pr1 = new ProcessRequest("storeD","queryObj"); 
     ThreadStart ts1 = new ThreadStart(pr1.Go); 
     Thread wrk = new Thread(ts1); 
     wrk.Start(); 
    } 
} 


class ProcessRequest 
{ 
    private string storeD; 
    private string queryObj; 

    public ProcessRequest(string storeD, string queryObj) 
    { 
     this.stroreD = storeD; 
     this.queryObj = queryObj; 
    } 

    public void Go() 
    { 
     try 
     {//your processing code here you can access $this->storeD and $this->queryObj 

     } 
     catch (Exception ex) 
     { 

     } 
    } 
} 
+0

Sie müssen wahrscheinlich einige Ereignisse hinzufügen, um zu sehen, wann der Prozess beendet wurde, hängt davon ab, was Sie wirklich tun. d. H. In ProcessRequest öffentlicher Delegierter void ProcessFinished (ProcessRequest req); öffentliche Veranstaltung ProcessFinished EFinished; am Ende Ihrer Go() Methode: if (this.Finished! = Null) EFinished (this); So können Sie bei Bedarf das Ende-Ereignis verarbeiten: pr1.Finished + = new ProcessRequest.ProcessFinished (pr1_EFinished); void pr1_EFinished (ProcessRequest req) {} Ich denke, es gibt viele Möglichkeiten, diese Katze zu häuten. – Gavin

0

Ich persönlich mag den Delegierten Route zu erstellen:

private delegate void StartDNIThreadDelegate(string storeID, string queryObject); 

private static void Main() 
{ 
    string storeID = "..."; 
    string queryObject = "..."; 
    StartDNIThreadDelegate startDNIThread = new StartDNIThreadDelegate(StartDNIThread); 
    IAsyncResult result = startDNIThread.BeginInvoke(storeID, queryObject, new AsyncCallback(StartDNIThreadDone), startDNIThread); 

    // Do non-threaded stuff... 

    result.AsyncWaitHandle.WaitOne(); // wait for thread to finish. 
} 

private static void StartDNIThread(string storeID, string queryObject) 
{ 
    // Do StartDNIThreading stuff. 
} 

private static void StartDNIThreadDone(IAsyncResult result) 
{ 
    StartDNIThreadDelegate startDNIThread = (StartDNIThreadDelegate)result.AsyncState; 

    // Do after thread finished cleanup. 

    startDNIThread.EndInvoke(result); 
}