10
votes

Envoyer des e-mails d'asynchronisation

J'utilise ASP.NET MVC 3 avec MVCMailer, j'ai essayé d'envoyer des e-mails à l'aide de Sendasync, mais il prend toujours plus de temps.

Donc, j'essaie d'utiliser la tâche comme le code ci-dessous: xxx

Le problème est que MVCMailer a besoin httpcontext, mais à l'intérieur de cette tâche, j'ai reçu httpcontext null.

Comment puis-je envoyer des courriers électroniques ASYNC?


0 commentaires

4 Réponses :


0
votes

Vous n'avez pas besoin de tâches. Sendasync est asynchrone et utilise un autre thread Soi. Les tâches n'accélèrent pas votre envoi.

Mise à jour : Lorsque je résoudre le même problème, j'utilise une tâche et un envoi synchronisé. Il semble que Sendasync n'était pas aussi asynchreux. Il s'agit d'un échantillon de mon code (il ne veut pas httpcontext): xxx


4 commentaires

Kirill, pourquoi cela prend plus longtemps? J'ai besoin d'envoyer un e-mail à l'arrière-plan.


L'asynchrone ne signifie pas vite. Cela signifie que votre processus lent ne bloquera pas votre thread de base et votre application réagira sur les actions des utilisateurs.


Bien sûr, mais lorsque j'envoie des courriels, le processus est bloqué par cette tâche.


BTW, je trouve mon propre code pour résoudre le même problème, j'ai également utilisé des tâches. Je mettez à jour ma réponse avec l'échantillon de mon code (il n'est pas besoin httpcontext)



4
votes

task.factory.startnew code> créera un nouveau fil.
Si vous souhaitez accéder à httpcontext strong> dans le fil principal, vous devez le faire:

public class HomeController : Controller
{
    private AutoResetEvent s_reset = new AutoResetEvent(false);

    public ActionResult Index()
    {
        var state = new WorkerState() { HttpContextReference = System.Web.HttpContext.Current };
        ThreadPool.QueueUserWorkItem(new WaitCallback(EmaiSenderWorker), state);

        try
        {
        s_reset.WaitOne();
        }
        finally
        {
        s_reset.Close();
        }

        return View();
    }

    void EmaiSenderWorker(object state)
    {
        var mystate = state as WorkerState;

        if (mystate != null && mystate.HttpContextReference != null)
        {
        System.Web.HttpContext.Current = mystate.HttpContextReference;
        }

        var mail = new UserMailer();
        var msg = mail.Welcome();
        msg.SendAsync();

        s_reset.Set();
    }

    private class WorkerState
    {
        public HttpContext HttpContextReference { get; set; }
    }

}


8 commentaires

Oui LeflyX! J'ai déjà essayé cela, mais je ne sais pas si c'est possible de transmettre la variable de contexte à l'objet MVCMailer.


@Michelandrade: j'ai mis à jour ma réponse. Essayez de voir si cela aide.


LeflyX, presque là, si je décolle "Task1.Wait ();" ça ne marche pas


@Michelandrade: ça fait pour moi. Créez-vous une nouvelle tâche dans une boucle? Je vous suggérerais de lire ceci: CODETHinked.com/net-40-AND-SystemThreadingTasks < / a>


@LEFLYX: N'oubliez-vous pas de jeter un oeil dans mon code? CODEPASTE.NET/7ACZ6U Je n'utilise pas le contrôle ASYNC, y a-t-il un problème?


Pas de problème, désolé de vous ennuyer. Merci de votre aide.


@Michelandrade: pas de problème. 50% de votre question ont des réponses non acceptées. Aider les autres parfois.


Avoir httpcontext sur deux threads en même temps est dangereux et non pris en charge par ASP.NET.



0
votes
public class UserMailer : MailerBase    
{
    RegisterService Service = new RegisterService();
    HttpContext Context;
    public UserMailer(HttpContext context)
    {
        Context = context;
        MasterName="_Layout";
    }

    public void ConfirmRegistration(Register model)
    {
        SendAsync(() =>
        {
            model.Conference = Service.Context.Conferences.Find(model.ConferenceID); // load conference bcs it fails to lazy load automatically.
            ViewData.Model = model;
            return Populate(x =>
            {
                x.Subject = "You registered for " + model.Conference.Name + "!"; ;
                x.ViewName = "Confirm";
                x.To.Add(model.Email);
            });
        });
    }

    private void SendAsync(Func<MvcMailMessage> GetEmail)
    {
        Task.Factory.StartNew(() =>
        {
            System.Web.HttpContext.Current = Context;
            GetEmail().Send();
        });
    }

1 commentaires

Merci d'avoir posté une réponse! Bien qu'un extrait de code puisse répondre à la question, il est toujours génial d'ajouter des informations supplémentaires autour, comme expliquer, etc.



19
votes

Un petit ajout à cela. Voici une méthode d'extension pour aider certains. XXX PRE>

Utilisez-le comme suit à partir de vos méthodes de contrôleur. P>

Mailers.UserMailer um = new Mailers.UserMailer();
um.SendWelcomeEmail(dataObject).SendEmailAsync(ControllerContext.HttpContext.ApplicationInstance.Context);


3 commentaires

Hey Matt! Merci pour la référence, cela a l'air génial, cela l'envoie-t-il de manière asynchrone 100%, j'ai entendu des gens disent que le mailateur MVC était un pseudo Async haha. Merci mon pote!


Pas de problème! Je frappais ma tête contre le bureau un peu avec celui-ci :)


Avoir httpcontext sur deux threads en même temps est dangereux et non pris en charge par ASP.NET.