我有一个小应用程序,可以在启动时搜索并存储大量文件的名称。我将这个搜索分成几个Thread对象,每个对象搜索一个目录,然后将结果推送回主线程。
当应用加载时,我会浏览每个线程并加载它:
foreach(Thread t in m_threads)
{
t.Start();
while(!t.IsAlive){}
}
当我在调试器中启动此应用程序时,它会加载并且线程会快速找到所有文件。但是,如果我从调试器外面开始它会冻结。将调试器附加到进程我可以看到IsAlive永远不会返回true。
我是C#线程的新手,所以有谁知道出了什么问题,或者我如何更容易地调试正在发生的事情?
答案 0 :(得分:3)
在对IsAlive进行检查之前,线程可能已经完成处理。
你还等什么,等一下检查IsAlive标志?
为什么不启动所有线程,然后在另一个循环中调用Join()等待线程完成?无需检查“IsAlive”。
更好的是,为什么不使用ThreadPool而不是自己启动一堆线程?
答案 1 :(得分:2)
这可能与事情冻结的原因无关,但你的实施是非常值得怀疑的。您枚举一组线程,启动每个线程,但然后阻塞直到线程完成?我认为你可能要做的就是启动所有线程,然后阻塞直到所有线程都完成。 (注意:这假设您打算写:“ while(t.IsAlive){} ”,因为等待线程启动更不合理。)
至于冻结,我们可能需要查看剩下的代码。既然你说你是C#线程的新手,并且看看你上面做了什么,我假设你也是线程新手,这意味着可能会有很多地方出现问题。
答案 2 :(得分:1)
您可能意味着IsAlive()
“永远不会返回虚假”。
好吧,如果是这样,那是因为你的线程继续无限执行。可能是你在这些线程中调用的方法有一个无限循环或其他东西。
答案 3 :(得分:1)
似乎我误解了我剪切和粘贴的代码以创建我的线程代码。我假设while(!t.isAlive){}行被阻塞,直到线程可以正常启动,并认为这是必要的管理。
我删除了该行,应用程序从调试器中启动。我稍后在代码中加入了线程,所以应该是它。
有没有“NEWB!”标签? :)
答案 4 :(得分:1)
使用您在上面提供的代码,在我看来,您想要按顺序启动线程。如果是这样,为什么你需要很多线程? 1个线程可以完成这项工作。
编辑:(在你回答之后)
确定。我看到你删除了有问题的一行。
即便如此,在您的情况下,我会考虑只使用一个线程来加载这些文件名,因为您只访问一个IO资源(磁盘)。每个线程都在竞争这个资源。您是否尝试在Windows中移动1个大文件,然后移动另一个大文件,而第一个仍在移动?磁盘性能下降。因此,我只为每个不同的IO资源创建一个线程。
答案 5 :(得分:1)
我建议不要持有一个Threads集合,而是使用Threadstarts。 如果您以后加入它们,则无需等到Thread运行,因此您不需要while循环。 确保您的线程被标记为后台线程,因此它们会在执行后自动清理。
我会这样做: 列出threadStarters = new List();
foreach (ThreadStart ts in threadStarters)
{
Thread t = new Thread(ts);
t.IsBackground = true;
t.Start();
}
答案 6 :(得分:0)
我完全不知道你在线程中做了什么,但我认为......
多线程+应用程序在附加调试器时表现不同=竞争条件
我很确定您遇到了一些同步问题。