如何发送电子邮件并同时保持我的应用程序响应?

时间:2017-01-14 23:14:43

标签: c# .net multithreading winforms

我有一个带有tabControl的应用程序,以及所有其他必要的控件。

因此,该应用程序的主要任务是发送电子邮件,如果我发送1,那么该应用程序无响应,最长2秒。 但是,如果我尝试发送像10那样..那使我的应用程序无响应20秒。现在,这并不像你想象的那么好。

我一直在尝试线程,但它一直给我一个关于UI操作的错误必须在拥有的线程中执行。

最后三行让我很难过,因为我从第一个ListView中抓取了tabControl中第一个Tab的名字,然后当我按下按钮时使用它们第二个选项卡,我尝试将它们传递给第三个选项卡,它们最终设置并进入第二个listView。

它可以工作,但它会使应用程序"暂停"在做这个过程的时候,我尝试使用线程,但我无法让它运行起来。

如何正确连接此功能或不进行线程?

using System;
using System.Net;
using System.Net.Mail;
using System.Windows.Forms;

namespace LearningTol
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void btnSend_Click(object sender, EventArgs e)
        {
            foreach(ListViewItem email in lvEmails.Items)
            {
                MailMessage msg = new MailMessage();
                msg.From = new MailAddress(tbUsername.Text);
                msg.To.Add(new MailAddress(email.Text));
                msg.Subject = "Subject";
                msg.Body = tbMessage.Text;
                msg.IsBodyHtml = false;

                SmtpClient client = new SmtpClient();
                client.Host = "smtp.gmail.com";
                client.Port = 587;
                client.Credentials = new NetworkCredential(tbUsername.Text, tbPassword.Text);
                client.EnableSsl = true;
                client.Send(msg);

                ListViewItem lvi = new ListViewItem(email.Text);
                lvi.SubItems.Add("Done!");
                lvFinishedEmails.Items.Add(lvi);
            }
        }
    }
}

这是一个更多" Visual"参考。 enter image description here

1 个答案:

答案 0 :(得分:4)

一个好的方法是使按钮点击处理程序asyncawait IO绑定工作,在这种情况下为SendAsync方法(而不是同步Send方法)。这也需要为您恢复正确的线程。所以你的代码看起来像是:

private async void btnSend_Click(object sender, EventArgs e)
{
    foreach(ListViewItem email in lvEmails.Items)
    {
        MailMessage msg = new MailMessage();
        msg.From = new MailAddress(tbUsername.Text);
        msg.To.Add(new MailAddress(email.Text));
        msg.Subject = "Subject";
        msg.Body = tbMessage.Text;
        msg.IsBodyHtml = false;

        SmtpClient client = new SmtpClient();
        client.Host = "smtp.gmail.com";
        client.Port = 587;
        client.Credentials = new NetworkCredential(tbUsername.Text, tbPassword.Text);
        client.EnableSsl = true;
        await client.SendMailAsync(msg);

        ListViewItem lvi = new ListViewItem(email.Text);
        lvi.SubItems.Add("Done!");
        lvFinishedEmails.Items.Add(lvi);
    }
}

顺便说一句,您通常不会返回async void方法,在使用Task时通常会返回Task<T>async,但事件处理程序是少数例外情况之一。