2016-11-20 30 views
1

我想要的東西做的我該如何平行化這種模式?

var docs = new LinkedList<string>(); 
for(int i = 0; ; ++i) 
{ 
    string html = client.DownloadString($"http://someforum.com/page?id={i}"); 
    if(html == null) 
     break; 
    docs.AddLast(html); 
} 

這相當於除了將利用以下事實:client.DownloadString($"http://someforum.com/page?id={i}");是可以在不同的線程得到運行長時間運行的任務。

基本上,我想要做的就是儘快從

"http://someforum.com/page?id=0""http://someforum.com/page?id=1",頁面獲取HTML ...

只是因爲我不從id=m得到一個頁面,然後我假設任何試圖獲得頁面id=n的任何任務n>m都不會獲得頁面並且可以關閉。

回答

3

你所想,使並行程序,有一個IO通話爲主要方面,所以它能夠更好地使用使用TaskCompletionSource異步編程,因爲WebclientDownloadAsync方法返回一個void。以下是ReadData修改後的版本:通過async方法,它可以await,直到所有的下載調用返回

public Task<string> ReadData(int i) 
{ 
    TaskCompletionSource<string> tcs = new TaskCompletionSource<string>(); 
    var client = new WebClient(); 
    string uriString = @"http://someforum.com/page?id=" + i; 
    client.DownloadStringCompleted += (sender,args) => 
    { 
     tcs.TrySetCanceled(); 
     tcs.TrySetException(args.Error); 
     tcs.TrySetResult(args.Result); 
    }; 

    client.DownloadStringAsync(new Uri(uriString)); 

    return tcs.Task; 
} 

調用READDATA異步

你可以最好做到這一點。另外,作爲其多個Async通話中,以便最好設置限制i,就像你不能檢查每個下載和返回的值同步的版本,所有來電都在這種情況下

public async Task<LinkedList<string>> ReadDataAsync() 
{ 
var docs = new LinkedList<string>(); 

List<Task<string>> taskList = new List<Task<string>>(); 

for (int i = 0; ; ++i) // Set a limit to i, since you are not running synchronously, so you cannot keep checking which value yields null as result 
{ 
    int localId = i; 
    taskList.Add(ReadData(localId)); 
} 

await Task.WhenAll(taskList); 

// Do Link List processing, if the Task is not cancelled and doesn't have an error, then result can be accessed 
} 
0

您可以使用Parallel類,而不是一起處理的任務。像這樣的東西

var docs = new LinkedList<string>(); 
var result = Parallel.For(0, N, n => 
{ 
    string html = new WebClient().DownloadString($"http://someforum.com/page?id={n}"); 
    if(html != null) 
    { 
     lock(docs) 
     { 
      docs.AddLast(html); 
     } 
    } 
}); 
+0

「WebClient」的實例成員不是線程安全的。 –

+0

我編輯了代碼。 – user1681317

+0

'LinkedList'也不是線程安全的。 ;) –