作者:一截藏青线 | 来源:互联网 | 2022-11-21 13:34
我正在开发一个项目,为用户显示,读取(使用语音)和邮件通知.
一切正常,但我有一个问题,我无法找到答案.
每次我需要调用扬声器类时,我需要创建一个新线程.实际上,我正在使用大量的线程来完成后台工作并更新一些信息.
我怀疑:
调用这样的新线程:
public void relatmailth()
{
MAILRELAT mails = new MAILRELAT();
relatmail = new Thread(new ThreadStart(mails.mail));
relatmail.IsBackground = true;
relatmail.Start();
}
每次我需要发送电子邮件,都是不好的做法?
该程序将自动管理线程?
在调用新线程之前,我需要"杀死"(我知道不推荐)旧线程吗?
如果是的话,我该如何解决这个问题呢?
1> Eric Lippert..:
一切正常
......可能是偶然的.
每次我需要调用扬声器类时,我需要创建一个新线程.实际上,我正在使用大量的线程来完成后台工作并更新一些信息.
这是一个非常糟糕的做法.将线程视为工作者.如果您不雇用工人来完成任务,请不要雇用线程来完成任务.
每次我需要发送电子邮件,都是不好的做法?
每次你想发一封信,然后解雇他们,你会聘请一位新的行政助理吗?
是的,这是一个不好的做法.
在调用新线程之前,我需要"杀死"(我知道不推荐)旧线程吗?
当你知道答案时,为什么要问一个问题?从来没有杀死一个线程.这是非常危险的.如果您每次收到邮件时都聘请新的管理员,那么当邮件进入邮箱时,您是否会拍摄它们?
CLR保证在中止线程时保持其不变量.CLR不保证在中止线程时维护程序不变量.如果要中止某个线程,则应该在紧急情况下中止每个线程并关闭该进程,因为您担心运行线程会损坏用户数据.在这种紧急情况下,快速失败是最安全的关闭方式.
如果您没有处于紧急关闭状态,请不要杀死线程.
如果是的话,我该如何解决这个问题呢?
所有I/O任务 - 发送电子邮件,连接到数据库,读取和写入文件,连接到网络等 - 都应该使用单线程异步来完成.
所有CPU绑定任务应该是一个单独的进程,或者使用适当的高级任务调度技术(如TPL)分配一个工作线程. 不管理自己的线程.让TPL管理您的线程,并仅为其分配CPU绑定任务.
Re,"......如果你不雇用一个工人来完成一项任务,......"我认为这个比喻值得充实:你_could_说不断为新任务创造新线程然后让他们死任务完成就像在每次完成任务时裁员,然后每当你有新的东西要重新雇用他们时:它会给每项任务增加很多开销.然而,使用线程池就像拥有一个满是工作人员的房间,有些人可能处于闲置状态,他们随时准备开始执行任务.
@SolomonSlow:这是一个很好的类比.特别是因为你还在为那些闲散的工人付钱!CLR中的线程占用大量虚拟内存,即使它们处于空闲状态,因为CLR会提交整个堆栈.现在,当您将混合添加CPU时,事情会变得复杂一些.想象一个工人加CPU就像一个司机和一辆汽车.如果你有比汽车更多的司机,一些司机即使有交货也是闲置的.如果你有更多的汽车而不是司机,那么有些汽车可能正在使用中.
@SolomonSlow:如果其中一些司机负责执行IO任务,他们就会把车开到邮箱然后等待信件运营商到达,这是浪费他们的时间.你真正想要的是*与CPUs*一样多的线程,并且所有线程都在进行CPU限制工作.这就是你想要使用TPL的原因; 它的工作是弄清楚如何为CPU分配线程,以便以最低的资源成本获得最大的性能.