邮件发送程序&请求超时 [英] Mail Sending Program & Request Timeout

查看:155
本文介绍了邮件发送程序&请求超时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我被要求在asp.net上开发一个自动发送邮件程序。它应该发送5000封电子邮件,从数据库中读取地址。它肯定会陷入请求超时的困难。所以我似乎必须将其转换为Windows应用程序。但是我想知道这个网络应用程序是否会有所帮助。如果我编写Web服务,我的Web应用程序一次将邮件地址发送为50个列表。完成后,发送下一个50,依此类推。这有助于解决http请求超时的问题吗?

I was asked to develop an auto-mail sending program on asp.net. It is supposed to send, say 5000 e-mails reading the addresses from a database. It will sure fall into request timeout tough. So it seems I have to convert it into a windows app. But I'd like to know if ajaxifying this web-app would help. If I write a web service, and my web app sends the mail addresses as lists of 50 at a time. when done, send the next 50 and so on. Would this help to solve the problem of http request timeout?

推荐答案

使用webservice端点发送电子邮件是一个好主意,无论是从aspx类还是从客户端调用它使用javascript。

Using a webservice endpoint to send your emails is a good idea, whether you call it from an aspx class or from the client with javascript.

只需使用webservice调用即可生成一个线程来发送电子邮件并立即返回。

Simply use the webservice call to spawn a thread to send the emails and return immediately.

如果你想要视觉进度提示,那么写另一个ajax端点或aspx页面,它将显示电子邮件线程进度的状态。

If you wanted visual progress cues then write another ajax endpoint or aspx page that will display the status of the email thread's progress.

有很多方法可以实现这一点,你应该能够拿出一个给出的信息。

There are many ways to accomplish this, you should be able to come up with one with the information given.

从ajax批处理可能比你想做的工作更多,并增加了不必要的复杂性(从来没有一件好事。)

Batching from ajax is probably going to be more work than you want to do and adds unnecessary complexity (which is never a good thing).

这很有意思。我可能会加入这个并发布一些代码。

this is interesting. I may spike this and post some code.

好的,我回来了。你去吧。 webform ui和ajax ui。

Ok, im back. here ya go. both a webform ui and an ajax ui.

这些都不是完成产品 - 是支持故事的高峰。弯曲/折叠/主轴随意。

None of this is meant to be finished product - is a spike to support a story. bend/fold/spindle at will.

EmailService.asmx

using System;
using System.ComponentModel;
using System.Threading;
using System.Web.Script.Services;
using System.Web.Services;

namespace EmailSendingWebApplication
{
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [ToolboxItem(false)]
    [ScriptService]
    public class EmailService : WebService
    {
        private static EmailSendingProgress _currentProgress;
        private static Thread _emailThread;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="criteria">just an example</param>
        /// <param name="anotherCriteria">just an example</param>
        /// <returns></returns>
        [WebMethod]
        public EmailSendingProgress SendEmails(string criteria, int anotherCriteria)
        {
            try
            {
                if (_currentProgress != null && _emailThread.IsAlive)
                {
                    throw new InvalidOperationException(
                        "Email batch is already in progress. Wait for completion or cancel");
                }

                // use your criteria to cue up the emails to be sent.
                // .....
                // and derive a way for a thread to identify the emails
                // i am using a batchid

                int batchId = 1000; // contrived


                // create a thread

                _emailThread = new Thread(ProcessEmails);


                _currentProgress = new EmailSendingProgress
                                       {
                                           Status = ProcessState.Starting,
                                           BatchId = batchId
                                       };


                // you could use a 'state' object but this process/thread
                // is single use/single instance just access _currentProgress
                // by the static member

                _emailThread.Start();


                return _currentProgress;
            }
            catch (Exception ex)
            {
                _currentProgress = new EmailSendingProgress
                           {
                               Status = ProcessState.Error,
                               Message = "Error starting process:" + ex.Message
                           };
            }

            return _currentProgress;
        }

        [WebMethod]
        public EmailSendingProgress CancelEmailProcess()
        {
            if (_currentProgress != null && _emailThread.IsAlive)
            {
                _currentProgress.Cancel = true;
                _currentProgress.Message = "Cancelling";
            }

            return _currentProgress;
        }

        [WebMethod]
        public EmailSendingProgress GetProgress()
        {
            return _currentProgress;
        }

        private static void ProcessEmails()
        {
            // process your emails using the criteria, in this case, 
            // a batchId

            int totalEmails = 100;
            int currentEmail = 0;

            lock (_currentProgress)
            {
                _currentProgress.Total = totalEmails;
                _currentProgress.Status = ProcessState.Processing;
            }


            for (; currentEmail < totalEmails; currentEmail++)
            {
                lock (_currentProgress)
                {
                    if (_currentProgress.Cancel)
                    {
                        _currentProgress.Status = ProcessState.Cancelled;
                        _currentProgress.Message = "User cancelled process.";
                        break;
                    }
                    _currentProgress.Current = currentEmail + 1;
                }

                try
                {
                    // send your email
                    Thread.Sleep(100); // lallalala sending email
                }
                catch (Exception ex)
                {
                    // log the failure in your db

                    // then check to see if we should exit on error
                    // or just keep going.
                    lock (_currentProgress)
                    {
                        if (_currentProgress.CancelBatchOnSendError)
                        {
                            _currentProgress.Status = ProcessState.Error;
                            _currentProgress.Message = ex.Message;
                            break;
                        }
                    }
                }
            }

            {
                // don't want to obscure state/message from abnormal
                // termination..
                if (_currentProgress.Status == ProcessState.Processing)
                {
                    _currentProgress.Status = ProcessState.Idle;
                    _currentProgress.Message = "Processing complete.";
                }
            }
        }
    }

    public enum ProcessState
    {
        Idle,
        Starting,
        Processing,
        Cancelled,
        Error
    }

    [Serializable]
    public class EmailSendingProgress
    {
        public int BatchId;
        public bool Cancel;
        public bool CancelBatchOnSendError;
        public int Current;
        public string Message;
        public ProcessState Status;
        public int Total;
    }
}

WebFormUI.aspx

<%@ Page Language="C#" %>

<%@ Import Namespace="EmailSendingWebApplication" %>

<script runat="server">
    protected void Page_Load(object sender, EventArgs e)
    {
        var svc = new EmailService();
        UpdateProgress(svc.GetProgress());
    }

    protected void SendEmailsButton_Click(object sender, EventArgs e)
    {
        // arbitrary params - modify to suit
        string criteria = string.Empty;
        int anotherCriteria = 0;

        var svc = new EmailService();
        UpdateProgress(svc.SendEmails(criteria, anotherCriteria));
    }

    protected void CancelEmailProcessButton_Click(object sender, EventArgs e)
    {
        var svc = new EmailService();
        UpdateProgress(svc.CancelEmailProcess());
    }

    private void UpdateProgress(EmailSendingProgress progress)
    {
        SetButtonState(progress);
        DisplayProgress(progress);
    }
    private void DisplayProgress(EmailSendingProgress progress)
    {
        if (progress != null)
        {
            EmailProcessProgressLabel.Text = string.Format("Sending {0} of {1}", progress.Current, progress.Total);
            EmailProcessStatusLabel.Text = progress.Status.ToString();
            EmailProcessMessageLabel.Text = progress.Message;
        }
        else
        {
            EmailProcessProgressLabel.Text = string.Empty;
            EmailProcessStatusLabel.Text = string.Empty;
            EmailProcessMessageLabel.Text = string.Empty;
        }
    }

    private void SetButtonState(EmailSendingProgress progress)
    {
        if (progress != null &&
            (progress.Status == ProcessState.Starting || progress.Status == ProcessState.Processing))
        {
            CancelEmailProcessButton.Visible = true;
            SendEmailsButton.Visible = false;
        }
        else
        {
            CancelEmailProcessButton.Visible = false;
            SendEmailsButton.Visible = true;
        }
    }

    protected void RefreshButton_Click(object sender, EventArgs e)
    {
        // noop just to get postback. you could also use meta headers to refresh the page automatically 
        // but why?
    }
</script>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <br />
        EmailProcessStatus:
        <asp:Label ID="EmailProcessStatusLabel" runat="server" Text="EmailProcessStatus"></asp:Label>
        <br />
        EmailProcessProgress:
        <asp:Label ID="EmailProcessProgressLabel" runat="server" Text="EmailProcessProgress"></asp:Label>
        <br />
        EmailProcessMessage:<asp:Label ID="EmailProcessMessageLabel" runat="server" Text="EmailProcessMessage"></asp:Label>
        <br />
        <br />
        <asp:Button ID="SendEmailsButton" runat="server" OnClick="SendEmailsButton_Click"
            Text="Send Emails" />
        &nbsp;<asp:Button ID="CancelEmailProcessButton" runat="server" OnClick="CancelEmailProcessButton_Click"
            Text="Cancel Email Process" />
        <br />
        <br />
        <asp:Button ID="RefreshButton" runat="server" OnClick="RefreshButton_Click" Text="Refresh" />
    </div>
    </form>
</body>
</html>

AjaxUI.htm

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>

    <script type="text/javascript">
        //http://www.codeproject.com/Articles/38999/Consuming-ASP-net-WebServices-WCF-Services-and-sta.aspx

        var ProcessState = ["Idle", "Starting", "Processing", "Cancelled", "Error"];

        function createXHR() {
            var xhr;

            if (window.XMLHttpRequest) {
                xhr = new XMLHttpRequest();
            }
            else if (window.ActiveXObject) {
                xhr = new ActiveXObject('Microsoft.XMLHTTP');
            }
            else {
                throw new Error("Could not create XMLHttpRequest object.");
            }
            return xhr;
        }

        function emailAjax(operation, postData, callback) {

            var xhr = createXHR();

            xhr.open("POST", "EmailService.asmx/" + operation, true);
            xhr.onreadystatechange = function() {
                if (xhr.readyState === 4) {
                    callback(xhr.responseText);
                }
            };
            xhr.setRequestHeader("content-type", "application/json");
            xhr.send(postData);
        }

        function $(id) {
            var e = document.getElementById(id);
            return e;
        }
        function startProcess() {
            var postData = '{"criteria" : "something", "anotherCriteria" : "1"}';
            emailAjax("SendEmails", postData, displayProgress);
        }

        function cancelProcess() {
            emailAjax("CancelEmailProcess", null, displayProgress);
        }

        function getProgress() {
            emailAjax("GetProgress", null, displayProgress);
        }

        function displayProgress(json) {
            eval('var result=' + json + '; var prg=result.d;');

            $("EmailProcessMessage").innerHTML = "";
            $("EmailProcessStatus").innerHTML = "";
            $("EmailProcessProgress").innerHTML = "";
            $("CancelEmailProcessButton").style.display = "none";
            $("SendEmailsButton").style.display = "none";

            if (prg) {
                $("EmailProcessMessage").innerHTML = prg.Message;
                $("EmailProcessStatus").innerHTML = ProcessState[prg.Status];
                $("EmailProcessProgress").innerHTML = "Sending " + prg.Current + " of " + prg.Total;
            }

            if (prg && (prg.Status == 1 || prg.Status == 2)) {
                $("SendEmailsButton").style.display = "none";
                $("CancelEmailProcessButton").style.display = "inline";
            }
            else {
                $("CancelEmailProcessButton").style.display = "none";
                $("SendEmailsButton").style.display = "inline";
            }

        }

        function init() {
            $("SendEmailsButton").onclick = startProcess;
            $("CancelEmailProcessButton").onclick = cancelProcess;
            // kinda quick but we are only proccing 100 emails for demo
            window.setInterval(getProgress, 1000);


        }
    </script>

</head>
<body onload="init()">
    EmailProcessStatus:<span id="EmailProcessStatus"></span><br />
    EmailProcessProgress:<span id="EmailProcessProgress"></span><br />
    EmailProcessMessage:<span id="EmailProcessMessage"></span><br />
    <input type="button" id="SendEmailsButton" value="SendEmails" style="display: none" />
    <input type="button" id="CancelEmailProcessButton" value="CancelEmailProcess" style="display: none" />
</body>
</html>

这篇关于邮件发送程序&amp;请求超时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆