0

我正在尝试使用将一些变量传递给我的线程操作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() 方法,这样我就可以将搜索结果添加到面板中。

4

3 回答 3

3

你不需要将你的 UI 元素“传递”到你的ContinueWith方法中;捕获局部变量甚至直接访问实例变量都可以。

但是,您确实需要确保您的ContinueWith委托在 UI 线程上执行。您可以简单地通过使用带 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属性。

于 2012-05-28T18:41:23.417 回答
1

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

但是当线程访问控件时,你会得到跨线程异常。为防止这种情况,请在 UI 线程上运行延续:

.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()确保将继续分派回主线程。

于 2012-05-28T18:41:56.117 回答
1

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

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

于 2012-05-28T18:01:23.667 回答