我正在尝试创建一个简单的应用程序来计算我在主类中与单独的类中的歌曲数量,并且在计算它时会更新我的标签。所以我把我的音乐getmusic方法分解成了一个不同的对象。出于某种原因,当我创建第二个线程时,我的主线程不能继续工作。任何帮助将不胜感激我是编程的新手,所以如果有更好的方法来做到更有效,我会很乐意听取任何建议。
private void btnGetMusic_Click(object sender, EventArgs e)
{
getMus.GetMusic();
System.Threading.Thread MusThread = new System.Threading.Thread(getMus.GetMusic);
MusThread.IsBackground = true;
MusThread.Start();
while (true)
{
lblNumberOfSongs.Text = getMus.holder.Count.ToString();
}
}
答案 0 :(得分:1)
正如上面的人所评论的那样,你的while循环没有在后台线程中发生,它发生在主UI线程中。只有传递给线程新实例的方法(在本例中为getMus.GetMusic)才会在后台线程中运行。因此,由于你说while(true),while循环才会永远运行,这就是阻止你的UI响应的原因,而不是后台线程。
如果要在后台线程运行时不断更新标签,请尝试使用超时的连接语句。此外,您正在调用GetMusic一次,然后立即在后台线程中再次调用它,是否需要重复?你可以试试这个:
private void btnGetMusic_Click(object sender, EventArgs e)
{
System.Threading.Thread MusThread = new System.Threading.Thread(getMus.GetMusic);
MusThread.IsBackground = true;
MusThread.Start();
//this waits timeout # of milliseconds for the thread to be done
//if thread not done, update the label
//if thread done, exits while loop
while (!MusThread.Join(timeout))
{
lblNumberOfSongs.Text = getMus.holder.Count.ToString();
}
}
当它等待后台线程完全完成时,它仍然会挂起你的UI,但它不会永远挂起,除非后台线程实际上永远运行。
更好的方法是摆脱整个while循环,而在主UI表单上有一个计时器,将其设置为某个超时,并在启动线程之前启用它,然后在计时器滴答中事件代码,您更新标签,然后检查是否MusThread.IsAlive并禁用计时器。这样您的UI根本不会挂起。您需要将MusThread的声明移动为类字段而不是btnGetMusic_Click方法,否则它将超出范围且无法访问。
作为另一种选择,我还建议您可以不需要使用单独的线程来简单计算歌曲数量。我通常只在任务范围,复杂性和/或延迟非常大时才使用线程,因此可能会大大降低UI的响应速度。
现在,我不知道你说的是多少首歌,也许你有数十亿的歌曲,而且你不想让你的UI挂起来等待它全部计算。但是,如果你能够管理它,那么每次重新计算的一个更好的实现是在你的课程中添加或减少歌曲时保持一定数量的歌曲。然后count函数只返回运行总数,一个整数;基本上是即时的,不需要线程的麻烦和头痛。每次添加或删除歌曲时,您可能不会注意到增量或减量语句的开销。