我有一個很奇怪的問題。我的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