3

I am creating a web service
Inside the web service, I do some processing, which is very fast, I send 2 to 3 emails asynchronously using SmtpClient.SendAsync().

My problem is that even though they are being sent asynchronously, I have to wait for them to finish processing before ending the service and sending back a response to the user. If I don't wait for the SendCompletedEventHandler to fire, the email is never sent. Sometimes the mail server takes some time to respond.

The user doesn't really need to know if the emails were sent or not. It would be nice to just send the emails and let them process somewhere else and respond to the user as fast as I can.

Would anybody have a good solution for this? Maybe I'm wording my searches wrong but I'm not coming up with any solutions.

John Saunders
  • 160,644
  • 26
  • 247
  • 397
drexel sharp
  • 323
  • 1
  • 9
  • possible duplicate http://stackoverflow.com/questions/5036849/asynchronous-webservice-in-asp-net – Anas Aug 16 '12 at 23:58
  • You could switch off buffering for that method (if it is a webmethod) Try putting this attribute above it: [System.Web.Services.WebMethod(BufferResponse=false)] See http://msdn.microsoft.com/en-us/library/byxd99hx%28v=vs.71%29.aspx#vbtskusingwebmethodattributeanchorbufferresponse for more details – Louis Somers Aug 17 '12 at 00:08
  • Edited- I'm actually Creating the web service. Not making the call to one. So, basically I'm trying to do this inside the web service. asynchronously somehow. :/ – drexel sharp Aug 17 '12 at 00:09
  • Is there a reason you're using an ASMX web service and not using WCF? – John Saunders Aug 17 '12 at 01:04
  • @JohnSaunders - The only reason I'm not using WCF is basically cause I've never used it before. I was just sticking to what I know. I don't normally write web services. I'll DEFINITELY need to look into it though. Thanks for the suggestion – drexel sharp Aug 17 '12 at 16:32
  • You may want to see [More Reasons to Not use ASMX Services in New Code](http://johnwsaunders3.wordpress.com/2011/12/07/more-reasons-to-not-use-asmx-services-in-new-code/) – John Saunders Aug 17 '12 at 18:37

2 Answers2

1

You could fire up a new thread to do the sending:

ThreadPool.QueueUserWorkItem(delegate {
    SmtpClient client = new SmtpClient();
    // Set up the message here
    using (MailMessage msg = new MailMessage()) {
        client.Send(msg);
    }
});
Louis Somers
  • 2,560
  • 3
  • 27
  • 57
  • 1
    Thanks, this did work. I thought the asynchronous call by the SmtpClient WAS creating a thread to send emails. live and learn. Thanks for your reply! – drexel sharp Aug 17 '12 at 16:34
  • To tell the truth I have to agree that I don't understand exactly why SendAsync() doesn't work. this thread http://stackoverflow.com/questions/532791/whats-the-difference-between-queueuserworkitem-and-begininvoke-for-perform had some interesting info on it. Still I dont see why it would not work (though I do see it would work slower due to the queueing thing mentioned there). Maybe ASP detects spawned Async methods and calls EndInvoke() before serializing the response? (which might also save someones hide if the async function manipulates the response). But that's rather far fetched imho. – Louis Somers Aug 18 '12 at 19:47
0

Here is a full example that I have tested and works with WCF. Control is returned immediately to the client, server starts sending, sleeps to simulate delay, then finishes. Just add a reference to System.ServiceModel to get the necessary classes.

class Program
{
    static void Main(string[] args)
    {
        ServiceHost host = new ServiceHost(typeof(HelloWorldService), new Uri("http://localhost:3264"));
        ServiceMetadataBehavior mdb = new ServiceMetadataBehavior();
        mdb.HttpGetEnabled = true;
        host.Description.Behaviors.Add(mdb);
        host.Open();

        Console.WriteLine("Service Hosting...");
        Console.ReadLine();
    }
}

[ServiceContract]
class HelloWorldService
{
    [OperationContract]
    public void SendEmails()
    {
        Task.Factory.StartNew(() =>
        {
            Console.WriteLine("Start Sending Emails...");
            Thread.Sleep(10000);
            Console.WriteLine("Finish Sending Emails...");
        });
    }
}

}

Despertar
  • 21,627
  • 11
  • 81
  • 79