这可能是我的一个愚蠢的错误,但我无法理解。
所以场景是我每200ms从数据库中检索一条记录,如果有的话。 在每条记录上,我开始一个线程。 在这种情况下,它是一封发送的邮件。
QMail mailRecord;
while (!stopSending)
{
if (QueueMailingHandler.m_numActive >= MaxThreads)
{
Thread.Sleep(2000);
continue;
}
mailRecord = QMail.Next();
if (mailRecord.UID > 0)
{
QueueMailingHandler.m_numActive++;
QueueMailingHandler MailingHandler = new QueueMailingHandler();
mailRecord.Processing = true;
MailingHandler.Start(mailRecord);
}
Thread.Sleep(200);
}
My MailingHandler:
internal QueueMailingHandler()
{
}
internal void Start(QMail rec)
{
record = rec;
Thread thread = new Thread(new ThreadStart(ProcessThread));
thread.IsBackground = true;
thread.Start();
}
public void ProcessThread()
{
_logging = new AutoQueueLog(record.UID.ToString(), "Sending Mails", record.Subject, "Processing");
_logging.Path = @"C:\Windows Services\QueueMailing\AutoLog";
_logging.LogMessage();
try
{
SendMail(record);
record.SetDone();
_logging.State = "Done";
_logging.LogMessage();
}
catch (Exception ex)
{
_logging.State = "Error";
_logging.LogException = ex;
_logging.Level = AutoLog.ExceptionLevel.Major;
_logging.LogMessage();
}
finally
{
m_numActive--;
}
}
作为伐木结果,我明白了:
6/16/2015 11:57:02 AM - [328] - Function : QueueMailingHandler.ProcessThread() - Processing
6/16/2015 11:57:02 AM - [329] - Function : QueueMailingHandler.ProcessThread() - Processing
6/16/2015 11:57:02 AM - [329] - Function : QueueMailingHandler.ProcessThread() - Done
6/16/2015 11:57:02 AM - [330] - Function : QueueMailingHandler.ProcessThread() - Done
6/16/2015 11:57:02 AM - [330] - Function : QueueMailingHandler.ProcessThread() - Processing
6/16/2015 11:57:02 AM - [331] - Function : QueueMailingHandler.ProcessThread() - Processing
6/16/2015 11:57:02 AM - [331] - Function : QueueMailingHandler.ProcessThread() - Done
6/16/2015 11:57:03 AM - [332] - Function : QueueMailingHandler.ProcessThread() - Processing
6/16/2015 11:57:03 AM - [333] - Function : QueueMailingHandler.ProcessThread() - Processing
6/16/2015 11:57:03 AM - [333] - Function : QueueMailingHandler.ProcessThread() - Done
6/16/2015 11:57:03 AM - [333] - Function : QueueMailingHandler.ProcessThread() - Done
6/16/2015 11:57:03 AM - [333] - Function : QueueMailingHandler.ProcessThread() - Done
问题是:为什么我的线程使用的对象应该是一个单独的(但类似的)线程?
欢迎任何帮助。感谢
答案 0 :(得分:1)
这是因为您为所有主题使用了record
的相同共享实例。
解决问题的一种简单方法是在启动线程时使用参数:
internal void Start(QMail rec)
{
Thread thread = new Thread(new ParameterizedThreadStart(ProcessThread));
thread.IsBackground = true;
thread.Start(rec);
}
然后,在线程中,使用参数而不是属性:
public void ProcessThread(object parameter)
{
var record = (QMail)parameter;
_logging = new AutoQueueLog(record.UID.ToString(), "Sending Mails", record.Subject, "Processing");
_logging.Path = @"C:\Windows Services\QueueMailing\AutoLog";
_logging.LogMessage();
try
{
SendMail(record);
record.SetDone();
_logging.State = "Done";
_logging.LogMessage();
}
catch (Exception ex)
{
_logging.State = "Error";
_logging.LogException = ex;
_logging.Level = AutoLog.ExceptionLevel.Major;
_logging.LogMessage();
}
finally
{
m_numActive--;
}
}
此外,以这种方式减少m_numActive
计数器将产生不可预测的结果。您应该使用线程安全的方法,例如Interlock.Decrement
方法:
Interlocked.Decrement(ref m_numActive);
最后但同样重要的是,您应该考虑每次使用线程池而不是创建新线程:
ThreadPool.QueueUserWorkItem(ProcessThread, rec);
答案 1 :(得分:0)
而不是这个
QMail mailRecord;
while (!stopSending)
{
if (QueueMailingHandler.m_numActive >= MaxThreads)
{
Thread.Sleep(2000);
continue;
}
mailRecord = QMail.Next();
if (mailRecord.UID > 0)
{
QueueMailingHandler.m_numActive++;
QueueMailingHandler MailingHandler = new QueueMailingHandler();
mailRecord.Processing = true;
MailingHandler.Start(mailRecord);
}
Thread.Sleep(200);
}
试试这个
while (!stopSending)
{
if (QueueMailingHandler.m_numActive >= MaxThreads)
{
Thread.Sleep(2000);
continue;
}
QMail mailRecord = QMail.Next();
if (mailRecord.UID > 0)
{
QueueMailingHandler.m_numActive++;
QueueMailingHandler MailingHandler = new QueueMailingHandler();
mailRecord.Processing = true;
MailingHandler.Start(mailRecord);
}
Thread.Sleep(200);
}
这里唯一的区别就是你声明你的QMail实例。