Async / await and IDisposable interface

I have a class that implements the IDisposable interface to host the private _MailMessage variable. In the same class, the async method is used, which uses the private IDisposable variable, namely async public Task<bool> Send My question is: will the usual implementation of IDisposable be a private variable after the asynchronous method completes? Here is an example of the class I'm talking about:

 public class Email : IEmail { private readonly IEmailData _EmailData; private MailMessage _MailMessage = new MailMessage(); public Email(IEmailData emailData) { if (emailData == null) { throw new ArgumentNullException("emailData"); } if (String.IsNullOrEmpty(emailData.To)) { throw new ArgumentNullException("emailData.To"); } if (String.IsNullOrEmpty(emailData.From)) { throw new ArgumentNullException("emailData.From"); } if (String.IsNullOrEmpty(emailData.FromName)) { throw new ArgumentNullException("emailData.FromName"); } if (String.IsNullOrEmpty(emailData.Subject)) { throw new ArgumentNullException("emailData.Subject"); } if (String.IsNullOrEmpty(emailData.Body)) { throw new ArgumentNullException("emailData.Body"); } _EmailData = emailData; } async public Task<bool> Send() { return await Task.Run<bool>(() => { using (SmtpClient smtp = new SmtpClient()) { smtp.Send(_MailMessage); } return true; }); } #region "IDisposable implementation" public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } ~Email() { Dispose(false); } protected virtual void Dispose(bool disposing) { if (disposing) { if (_MailMessage != null) _MailMessage.Dispose(); } } #endregion } 

I changed the implementation of IDisposable according to one of the answers suggesting not to use a destructor:

 #region "IDisposable implementation" public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (disposing) { if (_MailMessage != null) _MailMessage.Dispose(); } } #endregion 
+7
c # idisposable async-await
source share
2 answers

You are doing this quite fundamentally wrong. A good rule to keep in mind is that if you think you need a destructor, then you are mistaken in 99.9% of cases. A destructor is only required if you have a private variable of an unmanaged type that needs to be released. You will not do it. What you can tell you does the wrong thing when you discover that you are actually not doing anything at all if the order argument is false. Or, in other words, the destructor does virtually nothing. So it is not necessary. Then you also do not need a one-time template.

There are more errors, you need to inherit the IDisposable interface to implement your own Dispose () method. You forgot.

The Dispose () method must be called by the client code that instantiates your email class. You cannot call it yourself; you do not know when the client code stops using your email object. To quickly answer your question, you cannot get rid of the Send () method. There is no guarantee that the client code will really call it. You will need to leave it to the client code so that everything is correct.

+11
source share

I do not see you explicitly disposing of _MailMessage other than Email.Dispose .

async does nothing particularly magical with IDispose ; all you need to keep in mind is that async methods can return earlier.

So, if you call it like this:

 using (var email = new Email(...)) { await email.Send(); } 

Then your calling code (asynchronously) wait for the Send to complete before deleting the email . But if you call it this:

 Task task; using (var email = new Email(...)) { task = email.Send(); } 

Then your calling code will delete the email until Send complete.

+14
source share

All Articles