2009-09-04 9 views
5

Jak wywołać funkcję, która pobiera dwa parametry za pomocą wątków w języku C#? Muszę zadzwonić StartDNIThread (string, string storeID queryObject) z innego function.I muszą zdać dwa values.Both są strunoweThreading in C#

Odpowiedz

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

Albo z lambdas:

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

Otrzymuję następujący błąd: Wystąpił nieobsługiwany wyjątek typu "System.NullReferenceException" w kodzie App_gode.g2edzdox.dll Informacje dodatkowe: Odwołanie do obiektu nie jest ustawione na wystąpienie obiektu. – Janmejay

8

opcje są:

  • Kapsułkować parametry w nowej klasie, i umieść tę metodę dla delegata w tej klasie.
  • Użyj funkcji anonimowych (metody anonimowe lub wyrażenia lambda), aby automatycznie zrobić to samo z przechwyconymi zmiennymi.

To ostatnie jest ogólnie łatwiejsze. Nie wykazały co robisz z gwintem, ale można zrobić coś takiego:

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

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

Zauważ, że ponieważ zmienne są ujęte, nie należy zmieniać wartości dopiero po wiesz wątek faktycznie się zaczął. Można to obejść za pomocą przechwyconych zmienne używane tylko przez funkcję anonimową:

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 

Jest to szczególnie ważne, jeśli robisz coś w pętli, jak zmienne pętlowe się nie zmieni. Na przykład:

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

Jeśli używasz puli wątków lub innego sposobu uruchamiania wątków, wzór jest zasadniczo taki sam.

+0

upvote dla lambda. – Rap

2

Korzystanie z puli wątków:

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

Jeśli chcesz zrobić niektóre przetwarzania alternate-wątek udziałem UI, jesteś najlepszy pomocą BackgroundWorker.

1

Jest delegatem ParameterizedThreadStart których można użyć. Ten delegat wymaga metody, która przyjmuje jeden argument (obiektu tyoe). Tak więc, możesz użyć niestandardowego typu (klasa lub struktura), który zawiera 2 zmienne, które chcesz przekazać do ParameterizedThreadStart.

Jak to:

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

Ale w takich sytuacjach, wolę zrobić to w inny sposób. Wolę stworzyć niestandardowy typ "zadania", który usuwa wszystkie te rzeczy. Jak to:

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

staram się stworzyć coś podobnego obiektu zadanie następującym

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

Prawdopodobnie zechcesz dodać do tego zdarzenia, aby zobaczyć, kiedy skończył się proces, zależy od tego, co robisz naprawdę. tj. W ProcessRequest delegat publiczny unieważnił ProcessFinished (ProcessRequest req); wydarzenie publiczne ProcessFinished EFinished; na końcu swojej metody Go(): if (this.EFinished! = Null) EFinished (this); W ten sposób można przetworzyć w razie potrzeby zdarzenie zakończenia: pr1.EFinished + = new ProcessRequest.ProcessFinished (pr1_EFinished); void pr1_EFinished (ProcessRequest req) {} Chyba istnieje wiele sposobów na skórki tego kota. – Gavin

0

ja osobiście jak trasie Delegat:

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