在Task.Factory中传递变量

时间:2012-05-28 17:51:35

标签: c# .net lambda task-parallel-library

我正在尝试使用Task.Factory.StartNew();将一些变量传递给我的线程操作。 这是示例代码:

Task.Factory.StartNew(() =>
    {
        WebClient webClient = new WebClient();
        string source = webClient.DownloadString("http://localhost/?search=" + search_string);
        return source;
    })
.ContinueWith(result =>
    {
        search_string = search.Text;
        search_string = HttpUtility.UrlEncode(search_string, Encoding.UTF8).Replace("+", "%20");
    });

我想要的是将一个组框和一个面板传递给ContinueWith()方法,这样我就可以将搜索结果添加到面板中。

3 个答案:

答案 0 :(得分:2)

您无需将UI元素“传递”到ContinueWith方法中;捕获局部变量甚至直接访问实例变量都没问题。

但是,您需要确保您的ContinueWith委托在UI线程上执行。您只需使用an overload that takes a TaskScheduler,指定FromCurrentSynchronizationContext返回的调度程序:

即可实现此目的
Task.Factory.StartNew(() =>
    {
        WebClient webClient = new WebClient();
        string source = webClient.DownloadString(
            "http://localhost/?search=" + search_string);
        return source;
    })
.ContinueWith(antecedent =>
    {
        // Example use of result:
        this.resultTextBox.Result = antecedent.Result;
    },
    TaskScheduler.FromCurrentSynchronizationContext());

不要忘记传递给ContinueWith委托的参数是先行任务,而不是结果。要检索结果,请使用其Result属性。

答案 1 :(得分:1)

可能你不需要传递它们。您可以在lambda函数中简单地引用它们。请注意,您必须使用Invoke或Dispatcher来访问其他线程中的UI元素。

每个在不同lambda函数之间“共享”的变量必须在外部 lambda函数声明(闭包!!!!)。

答案 2 :(得分:1)

您不需要将变量(控件)传递给continuation;只是在延续代码中正常访问它们。

但是当线程访问控件时,您将获得跨线程异常。要防止这种情况,请在UI线程上运行continuation:

.ContinueWith(result => 
    { 
        search_string = search.Text; 
        search_string = HttpUtility.UrlEncode(search_string, Encoding.UTF8).Replace("+", "%20"); 
        // update the UI here (result.Result will contain the return value from the task)        
    }, 
    TaskScheduler.FromCurrentSynchronizationContext());

传递TaskScheduler.FromCurrentSynchronizationContext()可确保将继续传递回主线程。