多线程群发邮件,线程数由用户输入。可最终效果却是每个线程都要发一遍同样的邮件。怎么才能保证多个线程下一封邮件只发一次呢?邮件地址在一个ListBox里,用循环读ListBox的行数来取得邮址。

解决方案 »

  1.   

    代码比较烂,请大虾们将就着看看。分析分析。谢谢了!//使用用户设定的线程数来发邮件
    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;
    }
    }
      

  2.   

    做个异步的方法去发邮件不就可以了么,我觉得没有必要搞的这么复杂。
    这样写lock不还是每个线程重复做循环么。
      

  3.   

    那个lock是没有用的,应该加到哪里合适呢?
      

  4.   

    做一个  邮件地址-状态 的NameValue对 _address,默认状态都为N(未发送)。
    String GetOneAddress(){
      lock(this){
         //在这里循环去读_address,读到一个状态为N的,然后将状态置为P,返回地址。
         //如果所有的状态都为P,就是发完了,返回""
      }
    }
    每个线程的都先调GetOneAddress得到一个地址,然后再去发。
    private void sendMostMail(){
       String address = GetOneAddress();
       if(address.Equals(String.Empty)){
           //结束返回
       }
       //发邮件}
      

  5.   

    楼主的lock(this)锁的粒度太大了,性能损伤大
    如果列表里的地址发送完后,列表可移除的话,那是最好,这样就不会存在重发,如果不能移除,那就要判定当前项是否已发送了,当然可以把标志写在项的tag里,这样的话只要锁列表项即可,锁的粒度减少小了.流程很简单的,你自己再整理一下即可
      

  6.   

    不行啊。
    我是这样做的。
    设置类变量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);   
    }
    这个方法里执行。可还是重复的发送了多封邮件(和线程数一样)。奇怪。。