在c#中线程化

如何使用C#中的线程调用一个带两个参数的函数? 我必须从另一个函数调用StartDNIThread(string storeID,string queryObject)。我必须传递两个值。它们都是字符串

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

或者使用lambdas:

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

你的选择是:

  • 将参数封装在新类中,并将该方法用于委托到该类中。
  • 使用匿名函数(匿名方法或lambda表达式)自动对捕获的变量执行相同的操作。

后者通常更容易。 你还没有展示你在线程中做了什么,但你可能会做以下事情:

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

请注意,因为捕获了变量 ,所以在知道线程实际启动之后才能更改这些值。 您可以通过使用匿名函数仅使用的捕获变量来解决此问题:

 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 

如果你在循环中做任何事情,这一点尤为重要,因为循环变量本身会发生变化。 例如:

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

如果您正在使用线程池或任何其他方式启动线程,则模式基本相同。

使用线程池:

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

如果要进行涉及UI的备用线程处理,最好使用BackgroundWorker 。

您可以使用ParameterizedThreadStart委托。 这个委托需要一个带有一个参数(tyoe对象)的方法。 因此,实际上您可以使用自定义类型(类或结构),其中包含要传递给ParameterizedThreadStart的2个变量。

像这样:

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

但是,在这种情况下,我更愿意以另一种方式做到这一点。 我更喜欢创建一个自定义的“任务”类型,它抽象所有这些东西。 像这样:

 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. } } 

我倾向于创建一个类似于以下的任务对象

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

我个人喜欢代表路线:

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