webForumDet fria alternativet

Fil låst av annan process

.NET

6 svar · 615 visningar · startad av cok

Medlem sedan dec. 2005664 inlägg
Frågan#1

Hallå, jag har ett problem när jag läser av en mapp med pdf:er och skickar dessa som attachments i mail. Följande kod körs:

DirectoryInfo di = new DirectoryInfo(pathToScan);
FileInfo[] files = di.GetFiles("*.pdf");
foreach (FileInfo file in files)
{
    //ta ut användarens anställningsnummer från fil
    User u = getUserFromAnstNR(file.Name);
    sendMail(file, u);

    if (!string.IsNullOrEmpty(_backupPath))
    {
        if (!Directory.Exists(Path.Combine(_backupPath, DateTime.Now.Date.ToShortDateString())))
            Directory.CreateDirectory(Path.Combine(_backupPath, DateTime.Now.Date.ToShortDateString()));

        File.Copy(file.FullName, Path.Combine(Path.Combine(_backupPath, DateTime.Now.Date.ToShortDateString()), file.Name));
    }
    file.Delete();
}

//metod för att skicka mailet
bool sendMail(FileInfo file, User u)
{
    Attachment att = new Attachment(file.FullName);
    Language.Culture = u.CultureInfo;
    _message = Language.Message;
    _subject = Language.Subject;
    MailMessage m = new MailMessage(_from, u.Email, _subject, _message);
    m.Attachments.Add(att);
    Mail mail = new Mail();
    try
    {
        return mail.SendEmail(m);
    }
    catch (Exception e)
    {
        throw;
    }
}

Kan någon se nått galet i koden som skulle kunna få fram felmeddelandet?

Medlem sedan maj 20012 812 inlägg
#2

Jag misstänker att problemet är att du gör file.Delete på en referens som finns med i din files[] array.

Generellet är det en dålig ide att påverkar sin lista/array inne i en foreach-sats vilket kommer att genererar problem (om än inte det som du fått). Så testa att göra en vanlig for-loop i på dina files efter du skickat iväg alla mailen och där ta bort filen

FileInfo[] files = di.GetFiles("*.pdf");
foreach (FileInfo file in files)
{
    //ta ut användarens anställningsnummer från fil
    User u = getUserFromAnstNR(file.Name);
    sendMail(file, u);

    if (!string.IsNullOrEmpty(_backupPath))
    {
        if (!Directory.Exists(Path.Combine(_backupPath, DateTime.Now.Date.ToShortDateString())))
            Directory.CreateDirectory(Path.Combine(_backupPath, DateTime.Now.Date.ToShortDateString()));

        File.Copy(file.FullName, Path.Combine(Path.Combine(_backupPath, DateTime.Now.Date.ToShortDateString()), file.Name));
    }
}

for(int i = 0; i < files.Length; i++)
 files[i].Deltet();

Men detta är rena spekulationer, se även till så att du blir av med dina mail-objekt när du använt dem färdigt i din metohd, om det finns Dispose() på dem så kalla på den metoden. Du kanske skall köra din GarabageCollector innan du plockar bort filerna också, för att vara säker på att alla referenser till filen är släppt.

- M

Medlem sedan dec. 20014 239 inlägg
#3

Att kör GC (GarbageCollector) är väl inte sätt som är helt tillförlitligt. Att ropa på GC kan vara bra men du vet inte exact när den körs.

Men som Gladh påpekar ska du använda dispose om så är möjligt.

Medlem sedan maj 20012 812 inlägg
#4

zaiman skrev:

Att ropa på GC kan vara bra men du vet inte exact när den körs.

Jodå, du kan berätta för GC att du vill tömma den nu. Det fungerar bra, men problemet är att du oftast inte har bättre koll än systemet när det är mest lämpligt att köra en GC. Och när man gör en GC så måste systemet ställa sig i ett speciellt läge, vilket påverkar systemet, så därför brukar man överlämmna ansvaret för att tömma GC till systemet, men det fungerar inte alltid som man vill i sitt system och då måste man själv ta ansvar för det.

- M

Medlem sedan dec. 20014 239 inlägg
#5

Gladh skrev:

Och när man gör en GC så måste systemet ställa sig i ett speciellt läge, vilket påverkar systemet, så därför brukar man överlämmna ansvaret för att tömma GC till systemet.

Det var det jag syftade till ;)

Lite oklart formulerat av mig.. *sorry*

Medlem sedan juni 20008 205 inlägg
#6

Gladh skrev:

Generellet är det en dålig ide att påverkar sin lista/array inne i en foreach-sats vilket kommer att genererar problem (om än inte det som du fått).

Men arrayen i sig påverkas ju inte ett skvatt och oavsett om han kör Delete() på filen eller ej är ju objektreferensen fortfarande OK efter anropet, likaså objektets interna tillstånd. Finns det någon annan anledning?

Medlem sedan dec. 2005664 inlägg
#7

En dispose på MailMessage löste biffen. Tackar :)

255 ms totalt · 4 externa anrop · v20260731065814-full.6fe65c25
118 ms — deklarationer (db)
0 ms — hämta statistik (cache)
128 ms — hämta tråd, inlägg och bilagor (db)
124 ms — ändringar (db)