2012-05-28 31 views
0

我正在嘗試使用Task.Factory.StartNew();將一些變量傳遞給我的線程操作。 這是示例代碼:在Task.Factory中傳遞變量

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()方法,這樣我就可以搜索結果添加到面板上。

回答

1

可能你不需要傳遞它們。你可以簡單地在lambda函數中引用它們。請注意,您必須使用Invoke或Dispatcher從另一個線程訪問UI元素。

不同lambda函數之間「共享」的每個變量都必須聲明爲 lambda函數(closure !!!!)。

+0

那麼如何調用從其他線程獲取UI元素? – ItsGreg

+0

window.Invoke(someDelegate); ,有些Delegate是一個(委託)一個功能,可以做你想做的事情 – JohnB

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

您不需要將變量(控件)傳遞給繼續;只需在繼續代碼中訪問它們即可。

但是,當線程訪問控件時,會遇到跨線程異常。爲了防止這種情況,在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()確保持續分派回主線程。