我需要从网址列表中返回Dictionary<string, byte[]>
。
我有一个异步执行的代码示例,但只返回一个List<byte[]>
,另一个似乎正在强制转换对象但是引发了线程错误。
//Seems to assign to the output type correctly, but doesn't execute properly
async Task<Dictionary<string, byte[]>> ReturnFileData(IEnumerable<string> urls)
{
Dictionary<Uri, Task<byte[]>> dictionary;
using (var client = new WebClient())
{
dictionary = urls.Select(url => new Uri(url)).ToDictionary(
uri => uri, client.DownloadDataTaskAsync);
await Task.WhenAll(dictionary.Values);
}
return dictionary.ToDictionary(pair => Path.GetFileName(pair.Key.ToString()), pair => pair.Value.Result);
}
//Executes properly, but isn't returning the right output type
async Task<List<byte[]>> ReturnFileData2(IEnumerable<string> urls)
{
Dictionary<Uri, Task<byte[]>> dictionary;
var tasks = urls.Select(uri => new WebClient().DownloadDataTaskAsync(uri));
var results = await Task.WhenAll(tasks);
return results.Select(result => result).ToList();
}
如何处理ReturnFileData2()
并修正它以在输出中将Uri
的文件名与byte[]
一起投射?
答案 0 :(得分:3)
你应该坚持使用ReturnFileData,但重做它以为每个URL使用单独的客户端:
async Task<Dictionary<string, byte[]>> ReturnFileData(IEnumerable<string> urls)
{
Dictionary<Uri, Task<byte[]>> dictionary = urls
.Select(url => new Uri(url))
.ToDictionary(uri => uri, GetTheDataAsync);
await Task.WhenAll(dictionary.Values);
return dictionary
.ToDictionary(
pair => Path.GetFileName(pair.Key.ToString()),
pair => pair.Value.Result);
}
async Task<byte[]> GetTheDataAsync(Uri uri)
{
using (var client = new WebClient())
{
return await client.DownloadDataTaskAsync(uri);
}
}
答案 1 :(得分:1)
我建议您使用较新的HttpClient
:
async Task<Dictionary<string, byte[]>> ReturnFileDataAsync(IEnumerable<string> urls)
{
Dictionary<string, Task<byte[]>> dictionary;
using (var client = new HttpClient())
{
dictionary = urls.ToDictionary(uri => uri, client.GetByteArrayAsync);
await Task.WhenAll(dictionary.Values);
}
return dictionary.ToDictionary(pair => Path.GetFileName(pair.Key), pair => pair.Value.Result);
}
虽然我可能会这样写,但是避免使用中间字典:
async Task<Dictionary<string, byte[]>> ReturnFileDataAsync(IEnumerable<string> urls)
{
using (var client = new HttpClient())
{
var results = await Task.WhenAll(urls.Select(async url => new
{
Key = Path.GetFileName(url),
Value = await client.GetByteArrayAsync(url),
}));
return results.ToDictionary(x => x.Key, x => x.Value);
}
}