Home > Back-end >  C# Sending mail makes the UI thread stop and wait
C# Sending mail makes the UI thread stop and wait

Time:08-24

So i have alot a code running on one button press. Update excel file , sent mails to a list of mail adresses, reload excel into datagridview , clear listbox and textboxes, write a log text line inside a text file, disable some UI.

Now i have split the reloading excel file and writing log on a extra OK press from the user. Which helps a little. But still makes the program go unresponsive on sending mail and updating excel.

I don't think the updating excel is the issue. Its like 1 specific cell in about an average of 10 rows.

But the issue seems to be the mail sending. It awaits confirmation if mail has been sent and the mail server here is slow.

My mail sending code is this

SmtpClient smtpClient = new SmtpClient();
MailMessage message = new MailMessage();

If (System.IO.File.Exists(emailfile)
{
String[] Lines = System.IO.File.ReadAllLines(emailfile);
   Foreach (string line in Lines)
      message.To.Add(line);
}

Else
 {  System.IO.File.WriteAllText(emailfile,"");
TextWriter Email = new StreamWriter(emailfile, true);
Email.Writeline("[email protected]");
Email.close();
 }

try
{
MailAdress fromAddress = new MailAddress("[email protected]","order");
smtpClient.Host "";
smtpClient.Port xx;
smtpClient.credentials = ("""");
smtpClient.DeliveryMethod = SmtpDeliveryMethod.Network;
message.From = fromAddress;
message.Subject = "";
message.IsBodyHtml = True;
message.Body = Mybody();
message.DeliveryNotificationOptions = DeliveryNotificationOptions.OnFailure;
smtpClient.Send(message);
}

Catch (exception)
{
 MessageBox.Show("mail error");
}

I have read something about SendAsyc, I have also read something about task.run or task.factory.startnew There is also backgroundworker.

I don't understand which one i should use and how to implement it.

I do need the UI to wait(but not go unresponsive) for the mail to be sent and give a message box when it is done or failed.

CodePudding user response:

Using Async code would look something like

public async void OnButtonPress(){
  try{
     await SendEmail();
  }
  Catch (exception)
  {
     MessageBox.Show("mail error");
  }
}
private async Task SendEmail(){
   ...
   await smtpClient.SendMailAsync(...);
}

This is fairly safe, since all of your code will run on the UI-thread. A potential downside is that some *Async-methods are liars, and do significant work on the UI thread, so may not fully resolve the blocking issue. This approach also do not work with CPU-intensive code. So you may need to test this to see if it solves your problem.

The other alternative is to run the code synchronously on a background thread

public async void OnButtonPress(){
  try{
     await Task.Run(SendEmail);
  }
  Catch (exception)
  {
     MessageBox.Show("mail error");
  }
}
private void SendEmail(){
   // do work
}

The largest downside with this method is that the SendEmail method cannot access any UI-objects, and other shared data structures may need to be protected by locks. I would recommend reading up a bit about thread safety before doing anything involving multiple threads.

  • Related