C# 区分多个webclient结果

C# 区分多个webclient结果,c#,.net,webclient,C#,.net,Webclient,有一个清单 我想通过webclient.DownloadStringAsync下载每个url 我遇到的问题是: 我如何知道哪个e.结果对应于哪个url public class ressource{ public string url { get; set; } public string result { get; set; } } List<ressource> urlist = new List<ressource>(); urlist.Add(new ress

有一个清单

我想通过webclient.DownloadStringAsync下载每个url

我遇到的问题是: 我如何知道哪个e.结果对应于哪个url

public class ressource{
public string url { get; set; }
public string result  { get; set; }
}

List<ressource> urlist = new List<ressource>();
urlist.Add(new ressource(){url="blabla", result=string.empty});
....etc

var wc= new WebClient();
foreach(var item in urlist)
{
wc.DownloadStringCompleted += new DownloadStringCompletedEventHandler(wc_DownloadStringCompleted);
    wc.DownloadStringAsync(new Uri(item.url, UriKind.Absolute));
}

 void wc_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
 {
 urlist[?].result = e.Result; 
 }
公共类资源{
公共字符串url{get;set;}
公共字符串结果{get;set;}
}
List urlist=新列表();
添加(new ressource(){url=“blabla”,result=string.empty});
等
var wc=新的WebClient();
foreach(URL列表中的变量项)
{
wc.DownloadStringCompleted+=新的DownloadStringCompletedEventHandler(wc_DownloadStringCompleted);
DownloadStringAsync(新Uri(item.url,UriKind.Absolute));
}
void wc_DownloadStringCompleted(对象发送方,DownloadStringCompletedEventArgs e)
{
urlist[?].result=e.result;
}
我觉得完全卡住了。 谢谢你的想法

我遇到的问题是:如何知道哪个e.结果对应于哪个url

public class ressource{
public string url { get; set; }
public string result  { get; set; }
}

List<ressource> urlist = new List<ressource>();
urlist.Add(new ressource(){url="blabla", result=string.empty});
....etc

var wc= new WebClient();
foreach(var item in urlist)
{
wc.DownloadStringCompleted += new DownloadStringCompletedEventHandler(wc_DownloadStringCompleted);
    wc.DownloadStringAsync(new Uri(item.url, UriKind.Absolute));
}

 void wc_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
 {
 urlist[?].result = e.Result; 
 }
有各种不同的选项可供选择:

UserState

您可以将第二个参数传递给
DownloadStringAsync
,该参数可通过。例如:

// In your loop....
var wc = new WebClient();
wc.DownloadStringAsync(new Uri(item.url, UriKind.Absolute), item);

void wc_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
    var item = (ressource) e.UserState;
    item.result = e.Result;
}
多个网络客户端

您可以为循环的每个迭代创建一个新的
WebClient
,并向其附加一个不同的事件处理程序。lambda表达式在这里很有用:

// Note: this is broken in C# 3 and 4 due to the capture semantics of foreach.
// It should be fine in C# 5 though.
foreach(var item in urlist)
{
    var wc = new WebClient();
    wc.DownloadStringCompleted += (sender, args) => item.result = args.Result;
    wc.DownloadStringAsync(new Uri(item.url, UriKind.Absolute));
}
下载StringTaskAsync

您可以这样做,以便每个调用都返回一个
任务
。您可以保留这些元素的集合—在
urlist
中为每个元素保留一个集合—并知道哪种方式是这样的

或者,您可以同步获取所有结果,但我怀疑您不想这样做

其他信息

不幸的是,
WebClient
不支持多个并发连接,因此使用上述所有选项,您无论如何都应该在每次迭代中创建一个新的
WebClient

我遇到的问题是:如何知道哪个e.结果对应于哪个url

public class ressource{
public string url { get; set; }
public string result  { get; set; }
}

List<ressource> urlist = new List<ressource>();
urlist.Add(new ressource(){url="blabla", result=string.empty});
....etc

var wc= new WebClient();
foreach(var item in urlist)
{
wc.DownloadStringCompleted += new DownloadStringCompletedEventHandler(wc_DownloadStringCompleted);
    wc.DownloadStringAsync(new Uri(item.url, UriKind.Absolute));
}

 void wc_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
 {
 urlist[?].result = e.Result; 
 }
有各种不同的选项可供选择:

UserState

您可以将第二个参数传递给
DownloadStringAsync
,该参数可通过。例如:

// In your loop....
var wc = new WebClient();
wc.DownloadStringAsync(new Uri(item.url, UriKind.Absolute), item);

void wc_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
    var item = (ressource) e.UserState;
    item.result = e.Result;
}
多个网络客户端

您可以为循环的每个迭代创建一个新的
WebClient
,并向其附加一个不同的事件处理程序。lambda表达式在这里很有用:

// Note: this is broken in C# 3 and 4 due to the capture semantics of foreach.
// It should be fine in C# 5 though.
foreach(var item in urlist)
{
    var wc = new WebClient();
    wc.DownloadStringCompleted += (sender, args) => item.result = args.Result;
    wc.DownloadStringAsync(new Uri(item.url, UriKind.Absolute));
}
下载StringTaskAsync

您可以这样做,以便每个调用都返回一个
任务
。您可以保留这些元素的集合—在
urlist
中为每个元素保留一个集合—并知道哪种方式是这样的

或者,您可以同步获取所有结果,但我怀疑您不想这样做

其他信息


不幸的是,
WebClient
不支持多个并发连接,因此使用上述所有选项,您应该在每次迭代中创建一个新的
WebClient

另一种选择,也是我更喜欢的,是使用Microsoft的反应式框架(Rx)。它为您处理所有后台线程,类似于TPL,但通常更简单

我会这样做:

var query =
    from x in urlist.ToObservable()
    from result in Observable.Using(
        () => new WebClient(),
        wc => Observable.Start(() => wc.DownloadString(x.url)))
    select new
    {
        x.url,
        result
    };
现在将结果返回到原始的
urlist

var lookup = urlist.ToDictionary(x => x.url);

query.Subscribe(x =>
{
    lookup[x.url].result = x.result;
});

就这么简单。

另一种选择,也是我更喜欢的,是使用微软的反应式框架(Rx)。它为您处理所有后台线程,类似于TPL,但通常更简单

我会这样做:

var query =
    from x in urlist.ToObservable()
    from result in Observable.Using(
        () => new WebClient(),
        wc => Observable.Start(() => wc.DownloadString(x.url)))
    select new
    {
        x.url,
        result
    };
现在将结果返回到原始的
urlist

var lookup = urlist.ToDictionary(x => x.url);

query.Subscribe(x =>
{
    lookup[x.url].result = x.result;
});

就这么简单。

好吧,假设我在foreach循环中添加了新的webclient。我仍然不知道如何自动创建具有不同名称的事件hnd。这看起来很复杂,可能不是另一种方法吗?@acadea:我用各种选项编辑了我的答案。UserState正是我想要的。值得一提的是,即使在使用UserState时,webclient也应该在循环内创建,因为webclient不能有并发连接。你让我高兴极了@阿卡迪亚:有意思——我甚至不知道那里的限制。将编辑!是的,关于这一点有十几个问题:WebClient不支持并发I/O操作。我可以使用wc.isBusy对请求排序,这样就失去了“并发功能”,但仍然有UI响应OK,假设我在foreach循环中添加了新的webclient。我仍然不知道如何自动创建具有不同名称的事件hnd。这看起来很复杂,可能不是另一种方法吗?@acadea:我用各种选项编辑了我的答案。UserState正是我想要的。值得一提的是,即使在使用UserState时,webclient也应该在循环内创建,因为webclient不能有并发连接。你让我高兴极了@阿卡迪亚:有意思——我甚至不知道那里的限制。将编辑!是的,关于这一点有十几个问题:WebClient不支持并发I/O操作。我可以使用wc.isBusy对请求进行排序,这样就失去了“并发功能”,但用户界面仍然响应