如何以编程方式发送邮件而不冻结UI

时间:2015-05-27 11:29:05

标签: c# winforms

我有一个通过接收短信发送电子邮件的应用程序。我意识到这段代码smt.Send(mailMsg);我的UI冻结,直到发送过程完成,这有时需要2-5分钟,我不希望用户认为应用程序已崩溃或出现故障。因此,我想知道如何在后台工作程序中运行该方法,以避免冻结我的UI。以下是相关代码谢谢。

报告生成/导出方法

 private void Q4report()
    {
        Control.CheckForIllegalCrossThreadCalls = false;
        Output("Processing request...");
        ReportDocument cryRpt1 = new ReportDocument();
        cryRpt1.Load("cryQ2.rpt");
        crystalReportViewer2.ReportSource = cryRpt1;
        crystalReportViewer2.Refresh();
        cryRpt1.ExportToDisk(CrystalDecisions.Shared.ExportFormatType.PortableDocFormat, "QueryReport.pdf");
        Output("Generating report...");
        Output("Report Process Completed");
        if (i != 1)
        {
            sendMail("QueryReport.pdf", "4POS StockItem/per price list Query Report");
        }
        else if( i == 1)
        {
            Unsent_Request_sendMail("QueryReport.pdf", "4POS StockItem/per price list Query Report");
        }


    }

电子邮件发送方式

    public bool sendMail(string pdf, string subject)
    {
        bool flag = false;
        MailMessage mailMsg = new MailMessage();
        try
        {

            // To

            mailMsg.From = new MailAddress(radtxtEmail.Text);
            if (sub3 != null)
            {
                string strSubject = subject;
                string strBody = "Kindly find attached your query report.";

                mailMsg.To.Add(sub3);
                mailMsg.Subject = strSubject;
                mailMsg.Body = strBody;

                Attachment attachment = new Attachment(pdf);
                mailMsg.Attachments.Add(attachment);
                mailMsg.IsBodyHtml = true;

                using (SmtpClient smt = new SmtpClient("smtp.gmail.com"))
                {
                    smt.Port = 587;
                    smt.Credentials = new System.Net.NetworkCredential(radtxtEmail.Text, radtxtboxPassword.Text);
                    smt.EnableSsl = true;

                    bool connection = NetworkInterface.GetIsNetworkAvailable();

                    bool IsOnline = ModemManager.netCheck.IsOnline();

                    if (connection == true)
                    {
                        if (IsOnline == true)
                        {

                            smt.Send(mailMsg);
                            sent_insert();

                            mailMsg.Dispose();
                            attachment.Dispose();
                            Output("Report Mail successfully sent!");
                        }
                        else
                        {

                            Output("Internet Access Unavailable.");
                            Output("Mail process terminated.");
                            Unsent_insert();
                            mailMsg.Dispose();
                            attachment.Dispose();
                        //    btnSendMessage_Click();
                            return false;
                        }
                    }
                    else
                    {

                        Output("Network Connectivity Unavailable.");

                        Unsent_insert();

                        mailMsg.Dispose();
                        attachment.Dispose();
                  //      btnSendMessage_Click();
                        return false;
                    }

                }

                flag = true;


            }
        }

        catch (Exception ex)
        {

          Output(ex.Message);

        }


        return flag;

    }

2 个答案:

答案 0 :(得分:2)

您可以将sendMail方法封装在Task.Run块中,该块将在单独的线程上启动该方法:

Ext.override(Ext.form.field.Base, {
    initEvents: function() {
        var me = this,
        inputEl = me.inputEl,
            onFieldMutation = me.onFieldMutation,
            events = me.checkChangeEvents,
            len = events.length,
            i, event;
        if (inputEl) {
            me.mon(inputEl, Ext.supports.SpecialKeyDownRepeat ? 'keydown' : 'keypress', me.fireKey, me);
            for (i = 0; i < len; ++i) {
                event = events[i];
                if (event === 'propertychange') {
                    me.usesPropertychange = true;
                }
                if (event === 'textInput') {
                    me.usesTextInput = true;
                }
                me.mon(inputEl, event, onFieldMutation, me);
            }
        }
        me.callParent();
    },

    bindPropertyChange: function(active) {
        var method = active ? 'resumeEvent' : 'suspendEvent',
            inputEl = this.inputEl;
        if (this.usesPropertychange) {
            inputEl[method]('propertychange');
        }
        if (this.usesTextInput) {
            inputEl[method]('textInput');
        }
    }
});

请注意,除非您保存创建的任务,否则您将无法监控任务的完成状态,或在需要时取消它。如果这是用于UI,我将捕获创建的任务作为父类状态的一部分:

if (i != 1)
{
    Task.Run(() => sendMail("QueryReport.pdf", "4POS StockItem/per price list Query Report"));
}

然后附加从Task.Run创建的任务,以便在需要时有办法返回生成的任务:

private Task sendMailTask;

或者,如果由于按钮单击而触发此操作,则可以在异步void方法中等待它:

 if (i != 1)
{
    this.sendMailTask = Task.Run(() => sendMail("QueryReport.pdf", "4POS StockItem/per price list Query Report"));
}

仍会将控制权返回给用户界面并运行后台发送邮件的工作。

答案 1 :(得分:1)

使用BackgroundWorker防止冻结