Learn how to a build a cloud-first strategyRegister Now

x
?
Solved

Cannot access a disposed object (in SendCompletedCallback)

Posted on 2007-09-29
8
Medium Priority
?
891 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.");
        }
    }
0
Comment
Question by:newbieweb
  • 5
  • 3
8 Comments
 

Author Comment

by:newbieweb
ID: 19985832
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
0
 
LVL 22

Accepted Solution

by:
JimBrandley earned 2000 total points
ID: 19986015
I think you may be seeing trouble with this:
client.SendAsync(message, userState);
message.Dispose();

Since you are sending the message asychronously, it may be disposed befor you have finished with it. Try commenting out that dispose and see if your problem goes away.

Jim
0
 

Author Comment

by:newbieweb
ID: 19986849
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
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 22

Expert Comment

by:JimBrandley
ID: 19987181
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

0
 

Author Comment

by:newbieweb
ID: 19988746
thank you very much!

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

thanks,
nbw
0
 
LVL 22

Expert Comment

by:JimBrandley
ID: 19988763
My pleasure. Good luck nbw.

Jim
0
 

Author Comment

by:newbieweb
ID: 19991768
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
0
 

Author Comment

by:newbieweb
ID: 19994823
I'll post this seperately.

thanks.
0

Featured Post

NEW Veeam Backup for Microsoft Office 365 1.5

With Office 365, it’s your data and your responsibility to protect it. NEW Veeam Backup for Microsoft Office 365 eliminates the risk of losing access to your Office 365 data.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Today I had a very interesting conundrum that had to get solved quickly. Needless to say, it wasn't resolved quickly because when we needed it we were very rushed, but as soon as the conference call was over and I took a step back I saw the correct …
Calculating holidays and working days is a function that is often needed yet it is not one found within the Framework. This article presents one approach to building a working-day calculator for use in .NET.
Is your data getting by on basic protection measures? In today’s climate of debilitating malware and ransomware—like WannaCry—that may not be enough. You need to establish more than basics, like a recovery plan that protects both data and endpoints.…
Despite its rising prevalence in the business world, "the cloud" is still misunderstood. Some companies still believe common misconceptions about lack of security in cloud solutions and many misuses of cloud storage options still occur every day. …
Suggested Courses

864 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question