困惑好几天的问题。多线程群发邮件时如何确保每封邮件只发送一次?? 多线程群发邮件,线程数由用户输入。可最终效果却是每个线程都要发一遍同样的邮件。怎么才能保证多个线程下一封邮件只发一次呢?邮件地址在一个ListBox里,用循环读ListBox的行数来取得邮址。 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 代码比较烂,请大虾们将就着看看。分析分析。谢谢了!//使用用户设定的线程数来发邮件private void sendOK(){ sMTP = txtSMTP.Text.ToString(); port = Convert.ToInt32(txtPort.Text.ToString()); sMTPName = txtUserName.Text.ToString(); sMTPPSW = txtPSW.Text.ToString(); sendName = txtSendName.Text.ToString(); sendAddress = txtSendAddress.Text.ToString(); this.subject = this.txtSubject.Text.ToString(); this.content = this.mmContent.Text.ToString(); //获取用户设置线程数量 threadNum = Convert.ToInt32(this.spThreadNum.Text.ToString()); Thread[] sendThreadArry = new Thread[threadNum]; for(int i = 0; i<threadNum; i++) { sendThreadArry[i] = new Thread(new ThreadStart(sendMostMail)); } for(int i = 0; i<threadNum; i++) { sendThreadArry[i].Start(); }}//获取lbxMail中的邮件,判断是否发过,逐个发送邮件。private void sendMostMail(){ try { lock(this) { for(int i = 0; i<this.lbxMail.ItemCount; i++) { recipientEmail = this.lbxMail.GetItemText(i); sendMail(this.sendAddress,this.recipientEmail,this.sMTP,this.port,this.subject,this.content); lbxMail.SetSelected(i,true); lblMail.Text = recipientEmail; } } } catch(Exception ex) { MessageBox.Show(ex.ToString(),"提示信息",MessageBoxButtons.OK,MessageBoxIcon.Error); this.btnOK.Enabled = true; this.btnPlay.Enabled = true; }}//发邮件的具体方法private void sendMail(string sendEmail, string sendName,string recipientEmail, string recipientName, string smtp, int port,string smptName, string smtpPSW,string subject, string content){ OpenSmtp.Mail.EmailAddress send = new EmailAddress(sendEmail,sendName); EmailAddress recipient = new EmailAddress(recipientEmail,recipientName); MailMessage mail = new MailMessage(send,recipient); mail.Subject = subject; mail.Body = content; mail.Charset = "gb2312"; Smtp newSmtp = new Smtp(Smtp,SmtpName,SmtpPSW,Port); if (lbxMail.SelectedItem.ToString() == recipientEmail) { sendState = false; newSmtp.SendMail(mail); sendState = true; }} 做个异步的方法去发邮件不就可以了么,我觉得没有必要搞的这么复杂。这样写lock不还是每个线程重复做循环么。 那个lock是没有用的,应该加到哪里合适呢? 做一个 邮件地址-状态 的NameValue对 _address,默认状态都为N(未发送)。String GetOneAddress(){ lock(this){ //在这里循环去读_address,读到一个状态为N的,然后将状态置为P,返回地址。 //如果所有的状态都为P,就是发完了,返回"" }}每个线程的都先调GetOneAddress得到一个地址,然后再去发。private void sendMostMail(){ String address = GetOneAddress(); if(address.Equals(String.Empty)){ //结束返回 } //发邮件} 楼主的lock(this)锁的粒度太大了,性能损伤大如果列表里的地址发送完后,列表可移除的话,那是最好,这样就不会存在重发,如果不能移除,那就要判定当前项是否已发送了,当然可以把标志写在项的tag里,这样的话只要锁列表项即可,锁的粒度减少小了.流程很简单的,你自己再整理一下即可 不行啊。我是这样做的。设置类变量bool型的sendState,初始值为False,表示邮件没有发送。然后,用 toilingchen(努力学习ing) 推荐的办法写了个方法:private string GetOneAddress(){ lock(this) { //在这里循环去读_address,读到一个状态为N的,然后将状态置为P,返回地址。 //如果所有的状态都为P,就是发完了,返回"" for(int i = 0; i<this.lbxMail.ItemCount; i++) { if(sendState == false) { oneAddress = lbxMail.GetItemText(i); sendState = true; } } return oneAddress; }}如果sendState == false的话获取一条邮件地址,然后将sendState状态变为true返回oneAddress的值.然后在private void sendMostMail(){ recipientEmail = GetOneAddress(); sendMail(this.sendAddress,this.recipientEmail,this.sMTP,this.port,this.subject,this.content); }这个方法里执行。可还是重复的发送了多封邮件(和线程数一样)。奇怪。。 庞果网英雄会试题2大数相乘c#写法 gridview怎么动态显示“编辑,删除”这些字段 问个关于序列化的问题 如何让控件处于Designer状态? 加密算法 请教 C#中,如何捕捉SHIFT+TAB事件? 让datagrid中的某一行某一列(即某格子)或某一行只读,怎么做 问问C#是否可以编写引擎 关于定时调用程序, 看到这个问题的各位不要想简单了 在c# 环境下 fastreport3.2预览时怎么取消一些不想用的按钮 请问一个File.Create()的问题 dataSet怎么可以转换为string[]吗?
private void sendOK()
{
sMTP = txtSMTP.Text.ToString();
port = Convert.ToInt32(txtPort.Text.ToString());
sMTPName = txtUserName.Text.ToString();
sMTPPSW = txtPSW.Text.ToString();
sendName = txtSendName.Text.ToString();
sendAddress = txtSendAddress.Text.ToString(); this.subject = this.txtSubject.Text.ToString();
this.content = this.mmContent.Text.ToString(); //获取用户设置线程数量
threadNum = Convert.ToInt32(this.spThreadNum.Text.ToString()); Thread[] sendThreadArry = new Thread[threadNum]; for(int i = 0; i<threadNum; i++)
{
sendThreadArry[i] = new Thread(new ThreadStart(sendMostMail));
}
for(int i = 0; i<threadNum; i++)
{
sendThreadArry[i].Start();
}
}//获取lbxMail中的邮件,判断是否发过,逐个发送邮件。
private void sendMostMail()
{
try
{
lock(this)
{
for(int i = 0; i<this.lbxMail.ItemCount; i++)
{
recipientEmail = this.lbxMail.GetItemText(i);
sendMail(this.sendAddress,this.recipientEmail,this.sMTP,this.port,this.subject,this.content);
lbxMail.SetSelected(i,true);
lblMail.Text = recipientEmail;
}
}
}
catch(Exception ex)
{
MessageBox.Show(ex.ToString(),"提示信息",MessageBoxButtons.OK,MessageBoxIcon.Error);
this.btnOK.Enabled = true;
this.btnPlay.Enabled = true;
}
}
//发邮件的具体方法
private void sendMail(string sendEmail, string sendName,string recipientEmail, string recipientName, string smtp, int port,string smptName, string smtpPSW,string subject, string content)
{
OpenSmtp.Mail.EmailAddress send = new EmailAddress(sendEmail,sendName);
EmailAddress recipient = new EmailAddress(recipientEmail,recipientName);
MailMessage mail = new MailMessage(send,recipient);
mail.Subject = subject;
mail.Body = content;
mail.Charset = "gb2312";
Smtp newSmtp = new Smtp(Smtp,SmtpName,SmtpPSW,Port);
if (lbxMail.SelectedItem.ToString() == recipientEmail)
{
sendState = false;
newSmtp.SendMail(mail);
sendState = true;
}
}
这样写lock不还是每个线程重复做循环么。
String GetOneAddress(){
lock(this){
//在这里循环去读_address,读到一个状态为N的,然后将状态置为P,返回地址。
//如果所有的状态都为P,就是发完了,返回""
}
}
每个线程的都先调GetOneAddress得到一个地址,然后再去发。
private void sendMostMail(){
String address = GetOneAddress();
if(address.Equals(String.Empty)){
//结束返回
}
//发邮件}
如果列表里的地址发送完后,列表可移除的话,那是最好,这样就不会存在重发,如果不能移除,那就要判定当前项是否已发送了,当然可以把标志写在项的tag里,这样的话只要锁列表项即可,锁的粒度减少小了.流程很简单的,你自己再整理一下即可
我是这样做的。
设置类变量bool型的sendState,初始值为False,表示邮件没有发送。
然后,用 toilingchen(努力学习ing) 推荐的办法写了个方法:
private string GetOneAddress()
{
lock(this)
{
//在这里循环去读_address,读到一个状态为N的,然后将状态置为P,返回地址。
//如果所有的状态都为P,就是发完了,返回""
for(int i = 0; i<this.lbxMail.ItemCount; i++)
{
if(sendState == false)
{
oneAddress = lbxMail.GetItemText(i);
sendState = true;
}
}
return oneAddress;
}
}
如果sendState == false的话获取一条邮件地址,然后将sendState状态变为true返回oneAddress的值.
然后在
private void sendMostMail()
{
recipientEmail = GetOneAddress();
sendMail(this.sendAddress,this.recipientEmail,this.sMTP,this.port,this.subject,this.content);
}
这个方法里执行。可还是重复的发送了多封邮件(和线程数一样)。奇怪。。