C# 使用线程池下载字符串并等待下载完成
我正在使用WebClient上载字符串并从服务器检索答案。 为了更快地完成工作,我决定使用线程池,但我需要知道所有下载何时结束 到目前为止,我一直在使用一个倒计时事件,它应该在服务器的答案被处理后减少 我的主线程执行以下操作:C# 使用线程池下载字符串并等待下载完成,c#,multithreading,windows-phone-8,threadpool,countdownevent,C#,Multithreading,Windows Phone 8,Threadpool,Countdownevent,我正在使用WebClient上载字符串并从服务器检索答案。 为了更快地完成工作,我决定使用线程池,但我需要知道所有下载何时结束 到目前为止,我一直在使用一个倒计时事件,它应该在服务器的答案被处理后减少 我的主线程执行以下操作: CountdownEvent cde = new CountdownEvent(retour["contenu"].Count()); //Set the countdown with the number of Thread that needs to be creat
CountdownEvent cde = new CountdownEvent(retour["contenu"].Count()); //Set the countdown with the number of Thread that needs to be created
foreach (var tab in retour["contenu"])
{
App.AnniversaryViewModel.Items.Add(new Utilisateur(int.Parse((string)tab["id"])));
System.Diagnostics.Debug.WriteLine("Création d'un utilisateur avec l'id : " + (string)tab["id"]);
//System.Diagnostics.Debug.WriteLine("Le dernier utilisateur est : " + Items.Last<Utilisateur>().NOMPrenom);
ThreadPool.QueueUserWorkItem(App.AnniversaryViewModel.Items.Last<Utilisateur>().telechargerLesInfos , cde); //Starts the download
}
//Waiting for every Thread to be done
cde.Wait();
System.Diagnostics.Debug.WriteLine("On a fini d'attendre");
问题是委托拒绝执行,好像“cde.Wait()”也在强制处理委托的线程等待。
如何修复/避免此问题?首先,线程池在这里并没有真正起到任何作用。您仅在线程池中启动异步操作。开始这样的操作基本上不需要时间。你也可以在主线程中这样做 至于主线程被阻塞的原因;这很简单,您自己通过等待倒计时事件来阻止主线程 在异步操作完成之前,如果不阻塞主线程,就无法阻塞主线程。它们实际上是相互矛盾的要求
相反,您需要使整个程序异步,以避免阻塞主线程。例如,让此方法接受异步操作完成时应该执行的回调。另一个选项是使用任务并行库。任务使异步操作变得非常容易,特别是如果您能够利用
wait
关键字。我不确定我是否很了解如何做到这一点:我应该使TeleChargerleInfo方法异步吗?@grumlu有很多方法可以解决这个问题。您需要使该方法正确地异步。使用async
关键字是一种可能的方法;可能是最简单的选择,但不是唯一的选择。有几种方法可以使用回调使方法异步,或者使用不带async
关键字的任务,使用事件等。我明白你的意思,但我仍然不明白为什么APIWebTeam.sendRequest中的回调没有执行(它应该在主线程中执行吗?该方法应该是异步的吗?)@如果回调试图调用到主线程中,那么就是死锁;它正在主线程上等待,而主线程正在等待它。如果您想使用异步代码,那么基本上所有的东西都需要是异步的,因为任何长时间运行的操作都不会等待任何东西,而是总是安排在这些长时间运行的操作完成时触发的回调。
public void telechargerLesInfos(Object cde)
{
APIWebTeam.sendRequest(RequestType.PROFIL, (Newtonsoft.Json.Linq.JObject reponse) =>
{
processInfos(reponse); //Takes the answer from the server and parse it to fill private fields
((CountdownEvent)cde).Signal();
}, "&idProfil=" + id);
}