延迟文件读/写直到它被使用完毕?

时间:2011-11-07 14:37:39

标签: asp.net asp.net-mvc vb.net

我有一个生成PDF文件的vb.net MVC3 Razor应用程序。问题是,如果2个单独的用户同时单击打印按钮,则会抛出以下异常..:

  The process cannot access the file 'E:\web\xxxxxxxxxxsonl\PDF_Files\MailingLables.pdf' because it is being used by another process. 

  All of the controller actions to do with printing are basically like below:

 Function Ind_Cert(ByVal firstName As String, ByVal lastname As String, ByVal classRef As String)
        Dim _Attendance As attendance = db.attendances.Where(Function(f) f.Completed_Class = "Completed" And f.firstName = firstName And f.lastName = lastname).FirstOrDefault
        If Not IsNothing(_Attendance) Then
            Dim _reg_classes As List(Of reg_classes) = db.reg_classes.ToList
            Dim _registrants As List(Of reg_info) = db.reg_info.ToList
            Dim _courses As List(Of cours) = db.courses.ToList
            Dim _Board As List(Of board_members) = db.board_members.ToList
            Dim Board_Member As board_members = _Board.Where(Function(f) f.Official_Cap = "xxxxxx President").FirstOrDefault
            Dim RecordId As Integer = 0
            Dim conf_info As conf_info = db.conf_info.Single(Function(r) r.id = 0)
            Dim conf_num As Integer = conf_info.conf_number
            Dim _conf_num As String = conf_num.ToString
            Dim Length As Integer
            Dim _prefix As String = String.Empty

            If Str(conf_num) <> "" Then
                Length = Str(conf_num).Length
            End If


            Dim Divisor As Integer = 10 ^ (Length - 1)
            Dim conf_num_start As Integer = 0
            Dim Digits(Length - 1) As Integer

            While (conf_num > 10)

                'Extract the first digit
                Digits(conf_num_start) = Int(conf_num / Divisor)

                'Extract remainder number - and store it back in Num
                conf_num = conf_num Mod Divisor

                'Decrease Divisor's value by 1/10th units
                Divisor /= 10

                'Increment Index
                conf_num_start += 1

            End While


            If conf_num = 0 Or 4 Or 5 Or 6 Or 7 Or 8 Or 9 Then _prefix = "th"
            If conf_num = 1 Then _prefix = "st"
            If conf_num = 2 Then _prefix = "nd"
            If conf_num = 3 Then _prefix = "rd"




            Dim pdfpath As String = Path.Combine(AppDomain.CurrentDomain.BaseDirectory) + "\PDF_Files\"
            Dim imagepath As String = Path.Combine(AppDomain.CurrentDomain.BaseDirectory) + "\PDF_Files\"
            Dim _PdfName As String = "Cert_" + lastname + ".pdf"
            Dim doc As New Document
            doc.SetPageSize(iTextSharp.text.PageSize.LETTER.Rotate())
            doc.SetMargins(1, 1, 1, 1)
            Dim _pageCounter As Integer = 0

            Dim Californian As BaseFont = BaseFont.CreateFont(Path.Combine(AppDomain.CurrentDomain.BaseDirectory) + "\Fonts\" + "CALIFB.TTF", BaseFont.CP1252, BaseFont.EMBEDDED)
            Dim Copper As BaseFont = BaseFont.CreateFont(Path.Combine(AppDomain.CurrentDomain.BaseDirectory) + "\Fonts\" + "COPRGTB.TTF", BaseFont.CP1252, BaseFont.EMBEDDED)
            Dim Bold_Times As BaseFont = BaseFont.CreateFont(BaseFont.TIMES_BOLD, BaseFont.CP1252, False)
            Dim BF_Times As BaseFont = BaseFont.CreateFont(BaseFont.TIMES_ROMAN, BaseFont.CP1252, False)
            Dim F_Name As New Font(BF_Times, 16, Font.BOLD, BaseColor.BLACK)
            Dim _Parking_Name As New Font(BF_Times, 18, Font.NORMAL, BaseColor.BLACK)
            Dim _Parking_Date As New Font(BF_Times, 24, Font.BOLD, BaseColor.BLACK)

            '**********************************Y lines for trial***********************************
            Dim y_line1 As Integer = 670
            Dim _Counter As Integer = 1
            Dim _Page As String = 1





            Dim _CertJpg As Image = Image.GetInstance(imagepath + "/cert.jpg")
            Dim imageWidth As Decimal = _CertJpg.Width
            Dim imageHeight As Decimal = _CertJpg.Height
            Dim writer As PdfWriter = PdfWriter.GetInstance(doc, New FileStream(pdfpath + _PdfName, FileMode.Create))
            doc.Open()
            Dim cb As PdfContentByte = writer.DirectContent


            If _Attendance.Completed_Class = "Completed" Then

                Dim _confInfo As conf_info = db.conf_info.Single(Function(a) a.id = 0)
                Dim year As String = Right(_confInfo.conf_start_date, 4)
                Dim _reg As reg_info = db.reg_info.Single(Function(b) b.id = _Attendance.reg_id)
                Dim name As String = _reg.first_name + " " + _reg.last_name
                Dim _dates As String = _confInfo.conf_start_date + " - " + _confInfo.conf_end_date
                Dim _course As cours = db.courses.Single(Function(c) c.course_ref = _Attendance.course_ref)
                Dim _className As String = _course.course_title.ToString
                Dim _hours As String = _course.course_hours
                Dim _certName As String = Board_Member.First_Name + " " + Board_Member.last_name


                _CertJpg.Alignment = iTextSharp.text.Image.UNDERLYING
                _CertJpg.ScaleToFit(792, 611)
                doc.Add(_CertJpg)

                cb.BeginText()
                cb.SetFontAndSize(Californian, 36)
                cb.ShowTextAligned(PdfContentByte.ALIGN_CENTER, "CERTIFICATE OF COMPLETION", 396, 397.91, 0)
                cb.SetFontAndSize(Bold_Times, 22)
                cb.ShowTextAligned(PdfContentByte.ALIGN_CENTER, name, 396, 322.35, 0)
                cb.SetFontAndSize(Bold_Times, 16)
                cb.ShowTextAligned(PdfContentByte.ALIGN_CENTER, _hours + " Hours", 297.05, 285.44, 0)
                cb.SetFontAndSize(Bold_Times, 16)
                cb.ShowTextAligned(PdfContentByte.ALIGN_CENTER, _dates, 494.95, 285.44, 0)
                cb.SetFontAndSize(Bold_Times, 16)
                cb.ShowTextAligned(PdfContentByte.ALIGN_CENTER, "Class Attended: " + " " + _Attendance.course_ref + " -- " + _className, 396, 230.34, 0)
                cb.SetFontAndSize(Copper, 16)
                cb.ShowTextAligned(PdfContentByte.ALIGN_CENTER, _conf_num + _prefix + " Annual Conference " + _dates, 396, 193.89, 0)
                cb.SetFontAndSize(Bold_Times, 13)
                cb.ShowTextAligned(PdfContentByte.ALIGN_CENTER, _certName, 396, 175.69, 0)
                cb.SetFontAndSize(Bold_Times, 10)
                cb.ShowTextAligned(PdfContentByte.ALIGN_CENTER, "xxxxxxx President", 396, 162.64, 0)
                cb.EndText()

            End If

            doc.Close()
            Return _PdfName
        Else
            Return "Fail"
        End If


    End Function

这个错误发生就像我说的任何时候2个用户试图同时生成PDF文件。有人知道这个问题的解决方法吗?谷歌已经出现了无数页面,因为有人无法删除Windows中的文件,因为它正在被使用。但这并没有多大帮助..任何想法???

3 个答案:

答案 0 :(得分:2)

您是否可以使用随机文件名创建PDF文件以避免首先发生冲突?

答案 1 :(得分:2)

你几乎可以做两件事。

  1. 在文件上添加锁定并阻止第二个(以及第三个和第四个等)直到锁定被清除

  2. 为每个实例创建一个唯一的文件。

  3. 我建议#2。您可以保留相同的文件名,只需将文件放在一个唯一的目录中即可。 GUID通常对我来说最简单:

    Dim pdfpath As String = Path.Combine(AppDomain.CurrentDomain.BaseDirectory) + "\PDF_Files\"
    pdfPath = Path.Combine(pdfPath, Guid.NewGuid.ToString())
    Directory.CreateDirectory(pdfPath)
    

    然后更改您的返回以包含上面创建的路径。

答案 2 :(得分:0)

将您的文件访问代码包裹起来。

  lock (this)
  {
     //Write file
  }

请参阅Lock on MSDN