我有一个很奇怪的问题。我的WebClient.DownloadDataCompleted
大多数时间不会启动。WebClient.DownloadDataCompleted not firing
我使用这个类:
public class ParallelFilesDownloader
{
public Task DownloadFilesAsync(IEnumerable<Tuple<Uri, Stream>> files, CancellationToken cancellationToken)
{
var localFiles = files.ToArray();
var tcs = new TaskCompletionSource<object>();
var clients = new List<WebClient>();
cancellationToken.Register(
() =>
{
// Break point here
foreach (var wc in clients.Where(x => x != null))
wc.CancelAsync();
});
var syncRoot = new object();
var count = 0;
foreach (var file in localFiles)
{
var client = new WebClient();
client.DownloadDataCompleted += (s, args) =>
{
// Break point here
if (args.Cancelled)
tcs.TrySetCanceled();
else if (args.Error != null)
tcs.TrySetException(args.Error);
else
{
var stream = (Stream)args.UserState;
stream.Write(args.Result, 0, args.Result.Length);
lock (syncRoot)
{
count++;
if (count == localFiles.Length)
tcs.TrySetResult(null);
}
}
};
clients.Add(client);
client.DownloadDataAsync(file.Item1, file.Item2);
}
return tcs.Task;
}
}
,当我在LINQPad孤立呼吁DownloadFilesAsync
,DownloadDataCompleted
之后半秒或所谓的,符合市场预期。
但是,在我的真实应用程序中,它根本不会触发,等待它完成的代码就会卡住。如评论所示,我有两个断点。他们没有被击中。
啊,但有时它确实会起火。相同的URL,相同的代码,只是一个新的调试会话。根本没有模式。
我检查可用线程的线程池:workerThreads> 30K,completionPortThreads = 999
我加10秒的休眠恢复之前,我的Web客户端都没有垃圾睡眠后检查收集和我的事件处理程序仍然附加。
现在,我跑出了想法来解决这个问题。
还有什么可能导致这种奇怪的行为?
我会说,上面的代码中,'clients'会超出范围并可能受到GC的打击。但是你指出,当你在这个方法中睡觉时,“客户”显然还在。如果你添加睡眠,下载是否工作?或者你仍然有同样的行为?你还需要多久才能下载所有的下载文件? – 2014-09-01 14:22:19
当你在没有附加调试器的情况下在VS中启动项目时,你会得到相同的行为吗? – 2014-09-01 14:23:24
@steve:添加睡眠不会改变行为,下载仍然不起作用。下载时间不到一秒钟,URL是用于localhost的,因此连接问题也不存在。由于传递给'cancellationToken.Register'的操作,'clients'不会超出范围。 – 2014-09-01 14:24:12