2009-09-04 14 views
5

Come chiamare una funzione che prende due parametri utilizzando il threading in C#? devo chiamare StartDNIThread (string storeID, string queryObject) da un altro function.I devono passare i due values.Both sono stringaThreading in C#

risposta

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

O con lambda:

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

Viene visualizzato il seguente errore Un'eccezione non gestita di tipo 'System.NullReferenceException' si è verificata in App_Code.g2edzdox.dll Ulteriori informazioni: Riferimento dell'oggetto non impostato su un'istanza di un oggetto. – Janmejay

8

Le opzioni disponibili sono:

  • incapsulare i parametri di una nuova classe, e metti il ​​metodo da usare per il delegato in quella classe.
  • Utilizzare funzioni anonime (metodi anonimi o espressioni lambda) per eseguire automaticamente la stessa operazione con le variabili acquisite.

Quest'ultimo è generalmente più facile, naturalmente. Non hai dimostrato quello che stai facendo con il filo, ma si potrebbe fare qualcosa di simile:

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

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

Nota che, poiché le variabili vengono catturati, non si dovrebbe modificare i valori fino a dopo si conosce il thread è effettivamente iniziato. È possibile aggirare il problema utilizzando le variabili catturati utilizzati solo dalla funzione anonima:

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 

Ciò è particolarmente importante se si sta facendo nulla in un ciclo, come le variabili di loop stessi cambierà. Per esempio:

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

Se si utilizza il pool di thread o qualsiasi altro modo di iniziare le discussioni, il modello è fondamentalmente la stessa.

+0

Upvote per lambda. – Rap

2

Utilizzando il ThreadPool:

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

Se si vuole fare un po 'di elaborazione alternativo-thread che coinvolge un utente, si sta meglio con il BackgroundWorker.

1

C'è un delegato ParameterizedThreadStart, che si può usare. Questo delegato richiede un metodo che accetta un argomento (di oggetto tyoe). Quindi, in effetti, puoi usare un tipo personalizzato (classe o struct) che contiene le 2 variabili che vuoi passare a ParameterizedThreadStart.

Ti piace questa:

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

Ma, in tali situazioni, preferisco farlo in un altro modo. Preferisco creare un tipo personalizzato 'Attività', che astrae tutte queste cose. Ti piace questa:

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

tendo a creare un qualcosa di oggetto un'attività simile al seguente

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

Probabilmente vuoi aggiungere alcuni eventi a questo per vedere quando il processo è finito, dipende da cosa stai facendo davvero. i.e in ProcessRequest delegato pubblico void ProcessFinished (ProcessRequest req); evento pubblico ProcessFinished EFinished; alla fine del metodo Go(): if (this.EFinished! = Null) EFinished (this); In questo modo è possibile elaborare se necessario l'evento di fine: pr1.EFinished + = new ProcessRequest.ProcessFinished (pr1_EFinished); void pr1_EFinished (ProcessRequest req) {} Immagino che ci siano molti modi per scuoiare questo gatto. – Gavin

0

Personalmente, come il percorso delegato:

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