• Welcome to TechPowerUp Forums, Guest! Please check out our forum guidelines for info related to our community.

StmpClient Problem in C#

Kreij

Senior Monkey Moderator
Joined
Feb 6, 2007
Messages
13,817 (2.20/day)
Location
Cheeseland (Wisconsin, USA)
I create a file on disk from my app, and then I want to send the file via e-mail.
This works fine by creating an SmtpClient and using the Send() method.

When the send completed I want to delete the file as there is no reason to save it any longer.

Code:
.... Code for creating file
SmtpClient _Client = new SmtpClient();
.... code for client configuration

try
{
    _Client.Send(myFile);
}
catch()
{
     ... handle an exception
}

System.IO.File.Delete(myFile);

The Send() method is supposed to block until finished, but this throws a "File in use by another process" exception on the Delete method.

So I then tried running the whole thing in a BackgroundWorker and then doing the file delete in the RunWorkerCompleted event. This too throws the same error.

It's seems that SmtpClient process still has a handle attached to the thread, but I'm not sure why it is not letting it go when it's done with the send.

Any ideas?


Oops .. title was supposed to be SmtpClient not StmpClient.
 
Last edited:

FordGT90Concept

"I go fast!1!11!1!"
Joined
Oct 13, 2008
Messages
26,259 (4.63/day)
Location
IA, USA
System Name BY-2021
Processor AMD Ryzen 7 5800X (65w eco profile)
Motherboard MSI B550 Gaming Plus
Cooling Scythe Mugen (rev 5)
Memory 2 x Kingston HyperX DDR4-3200 32 GiB
Video Card(s) AMD Radeon RX 7900 XT
Storage Samsung 980 Pro, Seagate Exos X20 TB 7200 RPM
Display(s) Nixeus NX-EDG274K (3840x2160@144 DP) + Samsung SyncMaster 906BW (1440x900@60 HDMI-DVI)
Case Coolermaster HAF 932 w/ USB 3.0 5.25" bay + USB 3.2 (A+C) 3.5" bay
Audio Device(s) Realtek ALC1150, Micca OriGen+
Power Supply Enermax Platimax 850w
Mouse Nixeus REVEL-X
Keyboard Tesoro Excalibur
Software Windows 10 Home 64-bit
Benchmark Scores Faster than the tortoise; slower than the hare.
I would make a second thread and public List<string>. The second worker thread just loops every five seconds or so and attempts to delete the files in the List<string> collection. If it succeeds, remove it from the list, if it fails, keep it in the list until next time.

I would only use this approach if the file is in a temp dir where it is a copy and won't be missed.


If that doesn't work either, instead of deleting using File.Delete, launch cmd.exe with the del [path] command. That worked in situations where File.Delete wouldn't.
 

FordGT90Concept

"I go fast!1!11!1!"
Joined
Oct 13, 2008
Messages
26,259 (4.63/day)
Location
IA, USA
System Name BY-2021
Processor AMD Ryzen 7 5800X (65w eco profile)
Motherboard MSI B550 Gaming Plus
Cooling Scythe Mugen (rev 5)
Memory 2 x Kingston HyperX DDR4-3200 32 GiB
Video Card(s) AMD Radeon RX 7900 XT
Storage Samsung 980 Pro, Seagate Exos X20 TB 7200 RPM
Display(s) Nixeus NX-EDG274K (3840x2160@144 DP) + Samsung SyncMaster 906BW (1440x900@60 HDMI-DVI)
Case Coolermaster HAF 932 w/ USB 3.0 5.25" bay + USB 3.2 (A+C) 3.5" bay
Audio Device(s) Realtek ALC1150, Micca OriGen+
Power Supply Enermax Platimax 850w
Mouse Nixeus REVEL-X
Keyboard Tesoro Excalibur
Software Windows 10 Home 64-bit
Benchmark Scores Faster than the tortoise; slower than the hare.
Oh, if Send causes the thread to pause until complete, you shouldn't need the second thread. You might just need to have the shell delete the file instead of your app.

I know I used cmd to copy a file that another application had a write stream open on. .NET would refuse to touch it but cmd didn't complain. It copied the file and then I could open a read stream on the copy and delete the copy once I was done.


I guess the question is: does the SMTP Client ever release the file (at least within reason)?
 

regexorcist

New Member
Joined
Feb 1, 2010
Messages
178 (0.03/day)
Location
~/
System Name Slackware Linux
Processor yes
Motherboard yes
Cooling currently convection, but considering mineral oil
Memory sometimes fails due to too much beer
Video Card(s) ATI Radeon HD5570 series
Storage IDE
Display(s) 32" LCD TV
Case sometimes
Audio Device(s) huh? what? speak up, I can't hear you
Power Supply yes
Software Slackware running Open-Source software (it doesn't get any better)

FordGT90Concept

"I go fast!1!11!1!"
Joined
Oct 13, 2008
Messages
26,259 (4.63/day)
Location
IA, USA
System Name BY-2021
Processor AMD Ryzen 7 5800X (65w eco profile)
Motherboard MSI B550 Gaming Plus
Cooling Scythe Mugen (rev 5)
Memory 2 x Kingston HyperX DDR4-3200 32 GiB
Video Card(s) AMD Radeon RX 7900 XT
Storage Samsung 980 Pro, Seagate Exos X20 TB 7200 RPM
Display(s) Nixeus NX-EDG274K (3840x2160@144 DP) + Samsung SyncMaster 906BW (1440x900@60 HDMI-DVI)
Case Coolermaster HAF 932 w/ USB 3.0 5.25" bay + USB 3.2 (A+C) 3.5" bay
Audio Device(s) Realtek ALC1150, Micca OriGen+
Power Supply Enermax Platimax 850w
Mouse Nixeus REVEL-X
Keyboard Tesoro Excalibur
Software Windows 10 Home 64-bit
Benchmark Scores Faster than the tortoise; slower than the hare.
According to that, it won't be fixed until .NET 4.0 (Visual Studio 2010) which isn't officially out yet.
 

Kreij

Senior Monkey Moderator
Joined
Feb 6, 2007
Messages
13,817 (2.20/day)
Location
Cheeseland (Wisconsin, USA)
That seems to be a different issue (not gracefully releasing the connection using QUIT).
I don't know how long SmtpClient keeps a handle on the file, and the rather frustrating part is that there is no good way in .Net to check for "file in use."

It seems that many people simply try to open a stream to the file and if it throws an exception because it is in use, retry until it succeeds, and then do whatever they want to do with the file.

This is a rather "expensive" way of checking to see if a file is in use.
You can also get a list of process handles, but you have to leave the realm of managed code to do it and this too seems like overkill. It's kind of like stopping at every house in the neighborhood to see if your friend lives there when you have his address in your pocket.

I can code around this by deleting the files at a different point in time, like looking for leftover files from a previous module run when the module starts, but that just doesn''t sit too well with my "clean up when your done" programming mentality. :D

Maybe I will just launch a GC thread at application start that periodically (once every 5 minutes or so) checks for the temporary files and deletes them if it can. (shrug)

@Ford : You're getting dangerously close to 5k posts. :toast: Do you have a custom title picked out yet?
 
Last edited:

FordGT90Concept

"I go fast!1!11!1!"
Joined
Oct 13, 2008
Messages
26,259 (4.63/day)
Location
IA, USA
System Name BY-2021
Processor AMD Ryzen 7 5800X (65w eco profile)
Motherboard MSI B550 Gaming Plus
Cooling Scythe Mugen (rev 5)
Memory 2 x Kingston HyperX DDR4-3200 32 GiB
Video Card(s) AMD Radeon RX 7900 XT
Storage Samsung 980 Pro, Seagate Exos X20 TB 7200 RPM
Display(s) Nixeus NX-EDG274K (3840x2160@144 DP) + Samsung SyncMaster 906BW (1440x900@60 HDMI-DVI)
Case Coolermaster HAF 932 w/ USB 3.0 5.25" bay + USB 3.2 (A+C) 3.5" bay
Audio Device(s) Realtek ALC1150, Micca OriGen+
Power Supply Enermax Platimax 850w
Mouse Nixeus REVEL-X
Keyboard Tesoro Excalibur
Software Windows 10 Home 64-bit
Benchmark Scores Faster than the tortoise; slower than the hare.
Opening a file stream isn't expensive. I'm pretty sure it comes straight from the NTFS table and it doesn't seek the hard drive unless you start reading or writing.

This is what I'd do (pseudocode):

Code:
internal volitile List<string> _DeleteFiles = new internal List<string>();
private Thread _Thread = null;
public void Start()
{
  _Thread = new Thread(Worker);
  _Thread.Start();
}
public void Stop()
{
  if (_Thread != null)
    _Thread.Abort();
}

public void Worker()
{
  while (true)
  {
    for (int i = _DeleteFiles.Count - 1; i >= 0; i--)
    {
      try
      {
        File.Delete(_DeleteFiles[i]);
        _DeleteFiles.RemoveAt(i);
      }
      catch  { }
    }
    Thread.Sleep(5000);
  }
}
If you got a file you want to delete, add it to the _DeleteFiles collection.
 
Joined
Dec 13, 2007
Messages
2,758 (0.46/day)
This might be too simple... but have you tried closing myfile?

Code:
.... Code for creating file
SmtpClient _Client = new SmtpClient();
.... code for client configuration

try
{
    _Client.Send(myFile);
}
catch()
{
     ... handle an exception
}
System.IO.File.Close(myfile);
{
System.IO.File.Delete(myFile);
 

FordGT90Concept

"I go fast!1!11!1!"
Joined
Oct 13, 2008
Messages
26,259 (4.63/day)
Location
IA, USA
System Name BY-2021
Processor AMD Ryzen 7 5800X (65w eco profile)
Motherboard MSI B550 Gaming Plus
Cooling Scythe Mugen (rev 5)
Memory 2 x Kingston HyperX DDR4-3200 32 GiB
Video Card(s) AMD Radeon RX 7900 XT
Storage Samsung 980 Pro, Seagate Exos X20 TB 7200 RPM
Display(s) Nixeus NX-EDG274K (3840x2160@144 DP) + Samsung SyncMaster 906BW (1440x900@60 HDMI-DVI)
Case Coolermaster HAF 932 w/ USB 3.0 5.25" bay + USB 3.2 (A+C) 3.5" bay
Audio Device(s) Realtek ALC1150, Micca OriGen+
Power Supply Enermax Platimax 850w
Mouse Nixeus REVEL-X
Keyboard Tesoro Excalibur
Software Windows 10 Home 64-bit
Benchmark Scores Faster than the tortoise; slower than the hare.
myFile is of type MailMessage (so File.Delete(myFile) will always error--can't delete MailMessage). So the files he would need to delete are probably under myFile.Attachments (an AttachmentCollection), no?

This has an example:
http://msdn.microsoft.com/en-us/library/system.net.mail.mailmessage.attachments.aspx

Code:
            MailMessage message = new MailMessage(
               "jane@contoso.com",
               "ben@contoso.com",
               "Quarterly data report.",
               "See the attached spreadsheet.");

            // Create  the file attachment for this e-mail message.
            Attachment data = new Attachment(file, MediaTypeNames.Application.Octet);
            // Add time stamp information for the file.
            ContentDisposition disposition = data.ContentDisposition;
            disposition.CreationDate = System.IO.File.GetCreationTime(file);
            disposition.ModificationDate = System.IO.File.GetLastWriteTime(file);
            disposition.ReadDate = System.IO.File.GetLastAccessTime(file);
            // Add the file attachment to this e-mail message.
            message.Attachments.Add(data);

What exactly are you trying to delete? If there isn't attachments, myFile = null would suffice.
 
Last edited:

Kreij

Senior Monkey Moderator
Joined
Feb 6, 2007
Messages
13,817 (2.20/day)
Location
Cheeseland (Wisconsin, USA)
Ford is correct. It's a PDF file that is created using the ReportDocument.ExportToDisk() method and then added as an attachment to the MailMessage.

@Cracker ... There is no System.IO.File.Close() method.
 
Joined
Dec 13, 2007
Messages
2,758 (0.46/day)
Ford is correct. It's a PDF file that is created using the ReportDocument.ExportToDisk() method and then added as an attachment to the MailMessage.

@Cracker ... There is no System.IO.File.Close() method.

o ok so it's physical never on the HD then? hince can't do the file.close method? never work with reportdocument or mailmessage yet.
 

FordGT90Concept

"I go fast!1!11!1!"
Joined
Oct 13, 2008
Messages
26,259 (4.63/day)
Location
IA, USA
System Name BY-2021
Processor AMD Ryzen 7 5800X (65w eco profile)
Motherboard MSI B550 Gaming Plus
Cooling Scythe Mugen (rev 5)
Memory 2 x Kingston HyperX DDR4-3200 32 GiB
Video Card(s) AMD Radeon RX 7900 XT
Storage Samsung 980 Pro, Seagate Exos X20 TB 7200 RPM
Display(s) Nixeus NX-EDG274K (3840x2160@144 DP) + Samsung SyncMaster 906BW (1440x900@60 HDMI-DVI)
Case Coolermaster HAF 932 w/ USB 3.0 5.25" bay + USB 3.2 (A+C) 3.5" bay
Audio Device(s) Realtek ALC1150, Micca OriGen+
Power Supply Enermax Platimax 850w
Mouse Nixeus REVEL-X
Keyboard Tesoro Excalibur
Software Windows 10 Home 64-bit
Benchmark Scores Faster than the tortoise; slower than the hare.
Ford is correct. It's a PDF file that is created using the ReportDocument.ExportToDisk() method and then added as an attachment to the MailMessage.
So is ExportToDisk or the Attachment not releasing the file? Can you try deleting the file after performing ExportToDisk to rule that out?
 
Last edited:

Kreij

Senior Monkey Moderator
Joined
Feb 6, 2007
Messages
13,817 (2.20/day)
Location
Cheeseland (Wisconsin, USA)
I haven't had time to work on this problem, but thanks for the input guys.

I am assuming (I know, that's bad) that ExportToDisk() is releasing the file otherwise SmtpClient would have problems opening it to send it as an attachment.

Of course, with some if the internals of .Net it's anyone's guess. :D
 

FordGT90Concept

"I go fast!1!11!1!"
Joined
Oct 13, 2008
Messages
26,259 (4.63/day)
Location
IA, USA
System Name BY-2021
Processor AMD Ryzen 7 5800X (65w eco profile)
Motherboard MSI B550 Gaming Plus
Cooling Scythe Mugen (rev 5)
Memory 2 x Kingston HyperX DDR4-3200 32 GiB
Video Card(s) AMD Radeon RX 7900 XT
Storage Samsung 980 Pro, Seagate Exos X20 TB 7200 RPM
Display(s) Nixeus NX-EDG274K (3840x2160@144 DP) + Samsung SyncMaster 906BW (1440x900@60 HDMI-DVI)
Case Coolermaster HAF 932 w/ USB 3.0 5.25" bay + USB 3.2 (A+C) 3.5" bay
Audio Device(s) Realtek ALC1150, Micca OriGen+
Power Supply Enermax Platimax 850w
Mouse Nixeus REVEL-X
Keyboard Tesoro Excalibur
Software Windows 10 Home 64-bit
Benchmark Scores Faster than the tortoise; slower than the hare.
It depends on how Attachments work. If it is just copying a link and not the bytes, ExportToDisk() might be the culprit.
 
Top