我想使用c#async / await发送电子邮件,程序会根据标记“deleteFile”从计算机中删除附件。无论deleteFile标志的值是什么,电子邮件都成功传递,但是当我将deleteFile设置为true时,我收到以下异常。我必须发送两封单独的电子邮件,我只需要在第二封邮件后删除该文件。
发生了'System.IO.IOException'类型的未处理异常 mscorlib.dll中
其他信息:进程无法访问该文件 'C:\ Uploads \ TestFile.txt',因为它正由另一个进程使用。
你能帮我解决一下这个问题吗?
我的控制台应用程序代码是:
using System;
namespace SendMailAsyncDemo
{
class Program
{
private static string filePath = @"C:\Uploads\";
static void Main(string[] args)
{
Sender mailSender = new Sender();
mailSender.SendEmail("myemail@gmail.com", "Async mail with attachment", "Async mail with attachment body goes here ...", filePath + "TestFile.txt", false);
mailSender.SendEmail("anotheremail@gmail.com.com", "Async mail with attachment", "Async mail with attachment body goes here ...", filePath + "TestFile.txt", true);
Console.WriteLine("Email sent successfully!!!");
Console.ReadLine();
}
}
}
我有一个Sender类来发送电子邮件:
using System;
using System.IO;
using System.Net.Mail;
using System.Text;
using System.Threading.Tasks;
namespace SendMailAsyncDemo
{
public class Sender
{
public void SendEmail(string toEmail, string title, string body, string attachmentPath, bool deleteFile = false)
{
Task.Factory.StartNew(() =>
{
SendEmailAsync(toEmail, title, body, attachmentPath, deleteFile);
});
}
private async void SendEmailAsync(string toEmail, string title, string body, string attachmentPath, bool deleteFile)
{
Attachment attachment = null;
try
{
// class to hold all values from the section system.net/mailSettings/smtp in app.config
MailConfiguration smtpSection = new MailConfiguration();
using (MailMessage mailMsg = new MailMessage("<" + smtpSection.FromAddress + ">", toEmail))
{
mailMsg.IsBodyHtml = true;
mailMsg.Subject = title;
mailMsg.SubjectEncoding = Encoding.UTF8;
mailMsg.Body = body;
mailMsg.BodyEncoding = Encoding.UTF8;
if (!string.IsNullOrWhiteSpace(attachmentPath) && File.Exists(attachmentPath))
{
attachment = new Attachment(attachmentPath);
mailMsg.Attachments.Add(attachment);
}
using (SmtpClient smtpClient = new SmtpClient())
{
smtpClient.Timeout = 1000000;
smtpClient.UseDefaultCredentials = false;
if (deleteFile)
{
smtpClient.SendCompleted += (s, e) =>
{
attachment.Dispose();
File.Delete(attachmentPath);
};
}
await smtpClient.SendMailAsync(mailMsg);
}
}
}
catch (Exception ex)
{
Console.WriteLine("SendEmail exception: " + ex);
}
finally
{
Console.WriteLine("SendEmail done");
}
}
}
}
答案 0 :(得分:4)
正如评论中所讨论的那样,在维持相同的程序结构的同时,没有简单的方法来解决这个问题。特别是,由于您目前有两个正在进行的电子邮件发送呼叫而彼此不了解,因此无法确定何时可以安全执行删除。第二个Send
可以先完成。
我要做的更改 - 我删除了SendEmail
并让SendEmailAsync
public
和Task
返回。我还删除了删除后的概念:
public async Task SendEmailAsync(string toEmail, string title, string body, string attachmentPath)
{
try
{
// class to hold all values from the section system.net/mailSettings/smtp in app.config
MailConfiguration smtpSection = new MailConfiguration();
using (MailMessage mailMsg = new MailMessage("<" + smtpSection.FromAddress + ">", toEmail))
{
mailMsg.IsBodyHtml = true;
mailMsg.Subject = title;
mailMsg.SubjectEncoding = Encoding.UTF8;
mailMsg.Body = body;
mailMsg.BodyEncoding = Encoding.UTF8;
if (!string.IsNullOrWhiteSpace(attachmentPath) && File.Exists(attachmentPath))
{
Attachment attachment = new Attachment(attachmentPath);
mailMsg.Attachments.Add(attachment);
}
using (SmtpClient smtpClient = new SmtpClient())
{
smtpClient.Timeout = 1000000;
smtpClient.UseDefaultCredentials = false;
await smtpClient.SendMailAsync(mailMsg);
}
}
}
catch (Exception ex)
{
Console.WriteLine("SendEmail exception: " + ex);
}
finally
{
Console.WriteLine("SendEmail done");
}
}
然后按如下方式更改Main
:
static void Main(string[] args)
{
Sender mailSender = new Sender();
var send1 = mailSender.SendEmailAsync("myemail@gmail.com", "Async mail with attachment", "Async mail with attachment body goes here ...", filePath + "TestFile.txt");
var send2 = mailSender.SendEmailAsync("anotheremail@gmail.com.com", "Async mail with attachment", "Async mail with attachment body goes here ...", filePath + "TestFile.txt");
Task.WaitAll(send1,send2);
File.Delete(filePath + "TestFile.txt");
Console.WriteLine("Email sent successfully!!!");
Console.ReadLine();
}
如果这不是Main
/如果你正在使用尖端的C#,我还要async
使用await
几个WaitAll
在目前这一点,我得到了for word, count in top_words.items():
print word, count
。它是两个发送共同的最早代码,因此唯一可以确定 的代码片段可以安全地执行删除。