2009-09-04 7 views
5

Comment appeler une fonction qui prend deux paramètres en utilisant le filetage en C#? Je dois appeler StartDNIThread (chaîne storeID, chaîne queryObject) d'une autre function.I doivent passer les deux values.Both sont cordesFiletage dans C#

Répondre

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

Ou avec lambdas:

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

Je reçois l'erreur suivante Une exception non gérée de type 'System.NullReferenceException' s'est produite dans App_Code.g2edzdox.dll Informations complémentaires: La référence d'objet n'est pas définie sur une instance d'un objet. – Janmejay

8

Vos options sont:

  • encapsulent les paramètres d'une nouvelle classe, et mettez la méthode à utiliser pour le délégué dans cette classe.
  • Utilisez des fonctions anonymes (méthodes anonymes ou expressions lambda) pour faire la même chose automatiquement avec les variables capturées.

Ce dernier est généralement plus facile bien sûr. Vous ne l'avez pas montré ce que vous faites avec le fil, mais vous pourriez faire quelque chose comme:

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

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

Notez que parce que les les variables sont capturés, vous ne devriez pas modifier les valeurs jusqu'à ce que vous connaissez la thread a effectivement commencé. Vous pouvez contourner ce problème en utilisant des variables capturées uniquement utilisées par la fonction anonyme:

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 

Ceci est particulièrement important si vous faites quoi que ce soit dans une boucle, comme les variables de boucle eux-mêmes changer. Par exemple:

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

Si vous utilisez le pool de threads ou tout autre moyen de fils de départ, le modèle est fondamentalement la même.

+0

Upvote pour lambdas. – Rap

2

Utilisation du threadpool:

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

Si vous voulez faire un peu de traitement thread autre impliquant une interface utilisateur, vous êtes mieux à l'aide du BackgroundWorker.

1

Il y a un délégué ParameterizedThreadStart que vous pouvez utiliser. Ce délégué nécessite une méthode qui prend un argument (d'objet tyoe). Donc, en fait, vous pouvez utiliser un type personnalisé (classe ou struct) qui contient les 2 variables que vous voulez transmettre au ParameterizedThreadStart.

Comme ceci:

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

Mais, dans de telles situations, je préfère le faire d'une autre manière. Je préfère créer un type 'Tâche' personnalisé, qui résume toutes ces choses. Comme ceci:

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

J'ai tendance à créer un objet de tâche quelque chose comme le

suivant
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

Vous devez probablement ajouter quelques événements à cela pour voir quand le processing a fini, dépend de ce que vous faites vraiment bien. i.e dans ProcessRequest public delegate void ProcessFinished (ProcessRequest req); événement public ProcessFinished EFinished; à la fin de votre méthode Go(): if (this.EFinished! = Null) EFinished (this); De cette façon, vous pouvez traiter si besoin est l'événement de finition: pr1.EFinished + = new ProcessRequest.ProcessFinished (pr1_EFinished); void pr1_EFinished (ProcessRequest req) {} Je suppose qu'il y a plusieurs façons de soigner ce chat. – Gavin

0

Personnellement, je aime la route délégué:

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