2010-03-22 19 views

risposta

41

Supponiamo di avere un metodo:

void A(string a, int b) {} 

questo dovrebbe funzionare (NET 2.0):

ThreadStart starter = delegate { A("word", 10); }; 
Thread thread = new Thread(starter); 

thread.Start(); 

E la seguente (più breve) per le versioni superiori:

ThreadStart starter =() => A("word", 10); 
Thread thread = new Thread(starter); 

//or just... 
//Thread thread = new Thread(() => A("word",10)); 

thread.start() 
+0

'new Thread (() => A ("parola", 10))' per C# 3 +. – Dykam

+0

Esattamente. Stavo pensando a .NET 2.0. –

+0

@Dykam, puoi elaborare il significato di "() =>" nell'esempio fornito da te (nuovo Thread (() => A ("word", 10))) – Techee

4

Le soluzioni tsocks fornite potrebbero non essere valide per tutti ioni perché specifica i parametri al momento della creazione del delegato ThreadStart, invece che al momento dell'esecuzione. Ciò potrebbe causare errori perché i parametri potrebbero cambiare prima dell'esecuzione che probabilmente non è ciò che si desidera. Si supponga di dover creare più thread in un ciclo, ciascuna con il proprio parametri:

void CreateAndRunThreads() 
{ 
    List<ThreadStart> threadStartsList = new List<ThreadStart>(); 

    //delegate creation 
    for (int i = 0; i < 5; i++) 
    { 
     ThreadStart ts = delegate() { PrintInteger(i); }; 
     threadStartsList.Add(ts); 
    } 

    //delegate execution (at this moment i=5 in the previous loop) 
    foreach(ThreadStart ts in threadStartsList) 
    { 
     Thread t = new Thread(ts); 
     t.Start(); 
    } 
} 
private void PrintInteger(int i) 
{ 
    Debug.WriteLine("The integer value: "+i); 
} 

L'output qui è la seguente:

The integer value: 5 
The thread 0x17f0 has exited with code 0 (0x0). 
The integer value: 5 
The integer value: 5 
The thread 0x10f4 has exited with code 0 (0x0). 
The integer value: 5 
The thread 0x1488 has exited with code 0 (0x0). 
The integer value: 5 
The thread 0x684 has exited with code 0 (0x0). 

Si noti che tutti i delegati stampati il ​​valore 5, non da 0 a 4. Questo perché i delegati ThreadStart utilizzano la variabile "i", come è al momento dell'esecuzione, non al momento della creazione del delegato. Quindi qualsiasi modifica (i ++ nel ciclo) al parametro dopo il momento della creazione del delegato si rifletterà nel valore del parametro mentre il delegato viene eseguito.

Una soluzione a questo problema è utilizzare ParameterizedThreadStart e una classe personalizzata che aggrega tutti i parametri (se ce ne sono altri). Con parameterizedThreadStart, si passano i parametri al momento dell'esecuzione. Questo qualcosa sarebbe simile a questa:

class CustomParameters 
{ 
    public int IntValue { get; set; } 
    public string FriendlyMessage { get; set; } 
} 

private void CreateAndRunThreadsWithParams() 
{ 
    List<ParameterizedThreadStart> threadStartsList = new List<ParameterizedThreadStart>(); 

    //delegate creation 
    for (int i = 0; i < 5; i++) 
    { 
     ParameterizedThreadStart ts = delegate(object o) { PrintCustomParams((CustomParameters)o); }; 
     threadStartsList.Add(ts); 
    } 

    //delegate execution 
    for (int i=0;i<threadStartsList.Count;i++) 
    { 
     Thread t = new Thread(threadStartsList[i]); 
     t.Start(new CustomParameters() { IntValue = i, FriendlyMessage = "Hello friend! Your integer value is:{0}"}); 
    } 
} 

private void PrintCustomParams(CustomParameters customParameters) 
{ 
    Debug.WriteLine(string.Format(customParameters.FriendlyMessage, customParameters.IntValue)); 
} 

L'uscita è qui mostrato:

Hello friend! Your integer value is:1 
The thread 0x1510 has exited with code 0 (0x0). 
Hello friend! Your integer value is:0 
The thread 0x13f4 has exited with code 0 (0x0). 
Hello friend! Your integer value is:2 
The thread 0x157c has exited with code 0 (0x0). 
Hello friend! Your integer value is:3 
The thread 0x14e4 has exited with code 0 (0x0). 
Hello friend! Your integer value is:4 
The thread 0x1738 has exited with code 0 (0x0). 

(L'ordine di esecuzione non è deterministico, si tratta di una gara tra i fili)

4

per C# 3.0 puoi evitare il brutto array di oggetti che passa con metodi anonimi:

void Run() 
{ 
    string param1 = "hello"; 
    int param2 = 42; 

    Thread thread = new Thread(delegate() 
    { 
     MyMethod(param1,param2); 
    }); 
    thread.Start(); 
} 

void MyMethod(string p,int i) 
{ 

} 
0

uno dei modi più semplici t parametro di passaggio o di thread come

Thread xmlThread =new Thread(()=>WriteLog(LogTypes.Message, "Flag", "Module", "Location", "Text", "Stacktrace")); 
       xmlThread.Start(); 



private object WriteLog(LogTypes logTypes, string p, string p_2, string p_3, string p_4, string p_5) 
     { 

     } 
0
public void Start() 
     { 
      var t1 = new Thread((message) => { Console.WriteLine(message); }); 
      //the parametirized threadstart accepts objects, it is not generic 
      var t2 = new Thread(number => { var num = (int)number; 
      Console.WriteLine(num++); 
      }); 
      var t3 = new Thread((vals)=> work(vals)); 

      t1.Start(); 
      t2.Start(); 
      t3.Start(20); 
     } 

     public void work(params object[] vals) 
     { 

     }