We help IT Professionals succeed at work.

Cannot access a disposed object (in SendCompletedCallback)

curiouswebster
on
931 Views
Last Modified: 2013-12-17
Here is the code I am trying to debug that will send an email and get back a callback to tell me if the email went out okay.

The Send() function executes okay, but SendCompletedCallback has an error: Failure sending email.  Cannot access a disposed object.

Can anyone suggest what the errors may be caused by?

Thanks for the help,
nbw


        private static void SendCompletedCallback(object sender, AsyncCompletedEventArgs e)
        {
            // Get the unique identifier for this asynchronous operation.
            Email eMail = (Email) e.UserState;
           
            if (e.Cancelled)
            {
                eMail.SentOK = false;
                //Console.WriteLine("[{0}] Send canceled.", token);
            }
            if (e.Error != null)
            {
                eMail.SendError = e.Error.ToString();
                //Console.WriteLine("[{0}] {1}", token, e.Error.ToString());
            }
            else
            {
                eMail.SentOK = true;
                //Console.WriteLine("Message sent.");
            }
        }

        public void Send()
        {
            // Command line argument must the the SMTP host.
            SmtpClient client = new SmtpClient(Handles.SMTPServer);

            NetworkCredential nc = new NetworkCredential(Handles.Username, Handles.Password);
            client.UseDefaultCredentials = false;
            client.Credentials = nc;

            // Specify the e-mail sender.
            // Create a mailing address that includes a UTF8 character
            // in the display name.
            MailAddress from = new MailAddress(handles.FromEmail, handles.FromFirstName + " " + /*(char)0xD8+*/ handles.FromLastName, System.Text.Encoding.UTF8);

            // Set destinations for the e-mail message.
            MailAddress to = new MailAddress(this.eMailAddress);
           
            // Specify the message content.
            MailMessage message = new MailMessage(from, to);
            message.Body = "This is a test e-mail message sent by an application. ";
           
            // Include some non-ASCII characters in body and subject.
            string someArrows = new string(new char[] {'\u2190', '\u2191', '\u2192', '\u2193'});
            message.Body += Environment.NewLine + someArrows;
            message.BodyEncoding =  System.Text.Encoding.UTF8;
            message.Subject = "test message 1" + someArrows;
            message.SubjectEncoding = System.Text.Encoding.UTF8;
           
            // Set the method that is called back when the send operation ends.
            client.SendCompleted += new SendCompletedEventHandler(SendCompletedCallback);
           
            // The userState can be any object that allows your callback
            // method to identify this send operation.
            // For this example, the userToken is a string constant.
            Object userState = this;
            client.SendAsync(message, userState);
           
            //Console.WriteLine("Sending message... press c to cancel mail. Press any other key to exit.");
            //string answer = Console.ReadLine();
           
            // If the user canceled the send, and mail hasn't been sent yet,
            // then cancel the pending operation.
            /*if (answer.StartsWith("c") && mailSent == false)
            {
                client.SendAsyncCancel();
            }*/

            // Clean up.
            message.Dispose();
            //Console.WriteLine("Goodbye.");
        }
    }
Comment
Watch Question

curiouswebsterSoftware Engineer

Author

Commented:
Just to demonstrate...

NetworkCredential nc = new NetworkCredential(Handles.Username, Handles.Password);

translates to

NetworkCredential nc = new NetworkCredential("me@mydomain.com", "pw123");

and the FromEmail here: new MailAddress(handles.FromEmail,

is also me@mydomain.com
Top Expert 2007
Commented:
Unlock this solution and get a sample of our free trial.
(No credit card required)
UNLOCK SOLUTION
curiouswebsterSoftware Engineer

Author

Commented:
Jim,

It worked. Thanks!

Now how do you propose I dispose of the message?  Perhaps in the SendCompletedCallback?  Then the next question is how do I access the message.Dispose()?

Any ideas?

thanks,
nbw
Top Expert 2007

Commented:
According to MSDN, this is one of those classes where Dispose is needed. My mail service does it, but it doesn't use the asychronous send. There are two ways to attack this.
1. Don't use the asychronous send, or
2. Add a member to the class that contains these methods:
private MailMessage oldMessage = null.
Then in Send()
oldMessage = message;
And at the end of the callback:
oldMessage.Dispose();

If you go with the second approach, you will need to be very careful if you put this code into multiple worker threads.

Jim

curiouswebsterSoftware Engineer

Author

Commented:
thank you very much!

I intended to start from scratch if I wanted a multi-threaded model anyway.

thanks,
nbw
Top Expert 2007

Commented:
My pleasure. Good luck nbw.

Jim
curiouswebsterSoftware Engineer

Author

Commented:
Jim,

After sleeping on it I realized that it may not be as easy as what you'd described.  What if the call backs do not arrive in the sequence of the emails sent?

Wouldn't I be better off maintaining a list of email objects sent, then matching them up inside of SendCompletedCallback(), so I won't care if they lose their sequence?  And after a call back is received, I could delete the message from the list after logging the status to my database.

If this is the right approach, how would I go about matching them up?  How would I use a parameter of this function:

private static void SendCompletedCallback(object sender, AsyncCompletedEventArgs e)

to match up with a list containing this type:

 MailMessage message

thanks,
nbw
curiouswebsterSoftware Engineer

Author

Commented:
I'll post this seperately.

thanks.
Unlock the solution to this question.
Thanks for using Experts Exchange.

Please provide your email to receive a sample view!

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.