创建新的线程,传递参数

11

我想创建一个线程并把参数传递给它,但是我不知道怎么做。

Thread siteDownloader = new Thread(new ParameterizedThreadStart(GetHTML));

这是我想要启动为新线程的函数。

static string GetHTML(string siteURL)
{
    WebClient webClient = new WebClient();

    try
    {
        string sitePrefix = siteURL.Substring(0, 7);
        if (sitePrefix != "http://")
        {
            siteURL = "http://" + siteURL;
        }
    }
    catch
    {
        siteURL = "http://" + siteURL;
    }

    try
    {
        return webClient.DownloadString(siteURL);
    }
    catch
    {
        return "404";
    }
}

你预计如何使用返回值?你是否有访问任务并行库的机会? - R. Martinho Fernandes
将其通过TCP/IP连接发送到不同的计算机。如果我使用对象作为参数,ParameterizedThreadStart可以工作,但如果我使用字符串作为参数呢?我的意思是,我当然可以将obj转换为str,但也许有其他更好的方法? - Stan
不,那正是做法。但你不能仅仅从线程中返回一个值。 - R. Martinho Fernandes
1
如果你致力于.NET 4.0并且大量使用线程,那么使用TPL会让你的生活更加轻松。 - DaeMoohn
4个回答

22

就我个人而言,我总是使用捕获变量,即:

int a = ...
string b = ...
ThreadStart work = delegate {
    var result = DoSomethingInteresting(a, b);
    // push result somewhere; might involve a UI
    // thread switch
};
new Thread(work).Start();

这意味着在构建期间始终会检查其正确性,而不像传递对象参数那样。


好的答案。这提供了JavaScript中某种闭包概念。 - Faisal Mq

12

引用msdn的说法:

public class Work
{
    public static void Main()
    {
        // To start a thread using a shared thread procedure, use
        // the class name and method name when you create the 
        // ParameterizedThreadStart delegate. C# infers the 
        // appropriate delegate creation syntax:
        //    new ParameterizedThreadStart(Work.DoWork)
        //
        Thread newThread = new Thread(Work.DoWork);

        // Use the overload of the Start method that has a
        // parameter of type Object. You can create an object that
        // contains several pieces of data, or you can pass any 
        // reference type or value type. The following code passes
        // the integer value 42.
        //
        newThread.Start(42);

        // To start a thread using an instance method for the thread 
        // procedure, use the instance variable and method name when 
        // you create the ParameterizedThreadStart delegate. C# infers 
        // the appropriate delegate creation syntax:
        //    new ParameterizedThreadStart(w.DoMoreWork)
        //
        Work w = new Work();
        newThread = new Thread(w.DoMoreWork);

        // Pass an object containing data for the thread.
        //
        newThread.Start("The answer.");
    }

    public static void DoWork(object data)
    {
        Console.WriteLine("Static thread procedure. Data='{0}'",
            data);
    }

    public void DoMoreWork(object data)
    {
        Console.WriteLine("Instance thread procedure. Data='{0}'",
            data);
    }
}

所以你可以看到,创建一个方法并使用一个object作为参数,并将这个参数传递给Thread类的Start方法。


3

Rafal的解决方案是可行的,但我不确定您如何从中获得返回值。正如Martinho所指出的,ParameterizedThreadStart方法要求返回void类型。请尝试使用BackgroundWorker代替。

像这样调用它。

var bw = new BackgroundWorker();
bw.DoWork += new DoWorkEventHandler(bw_DoWork);
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
bw.RunWorkerAsync(url);

这里是DoWork,基本上是GetHTML的修改版。
static void bw_DoWork(object sender, DoWorkEventArgs e)
{
    WebClient webClient = new WebClient();
    string siteURL = (string)e.Argument;

    try
    {
        string sitePrefix = siteURL.Substring(0, 7);
        if(sitePrefix != "http://")
            siteURL = "http://" + siteURL;
    }
    catch
    {
        siteURL = "http://" + siteURL;
    }

    try
    {
        e.Result = webClient.DownloadString(siteURL);
    }
    catch
    {
        e.Result = "404";
    }
}

最后,在bw_RunWorkerCompleted中执行以下操作:
static void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    string result;
    result = (string)e.Result;
    //do something with result
}

1
你看过ParametrizedThreadStart的文档了吗?你需要一个带有对象参数并且不返回任何值的方法。因此,你需要相应地更改你的方法签名:
static void GetHTML(object data)
{
    string siteUrl = (string) data; // cast argument to string
    // blah blah
}

然后你需要想出一种使用返回值的方法。


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