2016-11-20 40 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'也不是线程安全的。 ;) –