C#中的线程处理

5

如何在C#中使用线程调用需要传递两个参数的函数? 我需要从另一个函数中调用StartDNIThread(string storeID, string queryObject),并传递这两个字符串参数。

6个回答

8
你的选择有:
  • 将参数封装在一个新类中,然后将用于委托的方法放入该类中。
  • 使用匿名函数(匿名方法或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();
}

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


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

或者使用Lambda表达式:

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

我遇到了以下错误:在 App_Code.g2edzdox.dll 中发生了未处理的 System.NullReferenceException 类型异常。附加信息:对象引用未设置为对象的实例。 - Janmejay

2

使用线程池:

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

如果你想在涉及UI的情况下进行一些替代线程处理,最好使用BackgroundWorker。请注意保留HTML标签。

1

有一个ParameterizedThreadStart委托可以使用。这个委托需要一个接受一个参数(类型为object)的方法。因此,实际上您可以使用一个包含要传递给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.
     }

}

0
我倾向于创建一个类似以下的任务对象。
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)
        {

        }
    }
}

你很可能想要添加一些事件来查看处理何时完成,但这实际上取决于你正在做什么。例如,在ProcessRequest中:public delegate void ProcessFinished(ProcessRequest req); public event ProcessFinished EFinished;在Go()方法的末尾:if (this.EFinished != null) EFinished(this);这样,您可以处理必要的完成事件:pr1.EFinished += new ProcessRequest.ProcessFinished(pr1_EFinished);void pr1_EFinished(ProcessRequest req) { }不过,我猜有很多种方法可以解决这个问题。 - Gavin

0

我个人比较喜欢使用委托(Delegate)这种方式:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接