Asp.net 使用异步从MemoryStream读取

Asp.net 使用异步从MemoryStream读取,asp.net,vb.net,asynchronous,Asp.net,Vb.net,Asynchronous,Im使用iTextSharp(并非与iTextSharp相关)生成PDF字节,代码如下: Function GetFileBytes() as Byte() Dim result() As Byte Using ms As New MemoryStream Dim reader As New PdfReader(pdfForm) Dim writer As New PdfStamper(reader, ms) Dim fields As

Im使用iTextSharp(并非与iTextSharp相关)生成PDF字节,代码如下:

Function GetFileBytes() as Byte()
Dim result() As Byte
    Using ms As New MemoryStream

        Dim reader As New PdfReader(pdfForm)
        Dim writer As New PdfStamper(reader, ms)

        Dim fields As AcroFields = writer.AcroFields

        fields.SetField("Customer Name", custInfo.FirstName + " " + custInfo.LastName)

        result = ms.GetBuffer
    End Using
End Function
我想将其改为异步任务,返回任务(字节()),但我在弄清楚如何使memorystream以异步模式写入以及如何在此过程中返回任务(字节())时遇到了问题。有什么建议吗?谢谢

编辑1 我想澄清使用任务和使用此代码的必要性,因为到目前为止,一些评论似乎都是“你为什么要这样做”和“不要这样做,我想礼貌地说“谢谢,但我想这样做”:

下面是我的场景,想象一个网站在几页上收集数据,然后显示一个审查屏幕,然后让用户能够查看包含该数据的PDF。在审查屏幕上,我需要生成一个1MB PDF文件,将其上载到BLOB存储,并在用户选择下载时使其可用


我想在用户查看查看屏幕时生成并上传PDF,而不是在用户选择“查看PDF”按钮时。这些代码将使用我的示例完成,这就是为什么我想知道如何创建Byte()类型的任务。欢迎提供任何帮助,再次感谢!

响应您的编辑:此场景很有意义。将所有内容包装到
任务中。运行
调用。确保线程安全(例如,不要在任务中使用HttpContext)。还应记录错误,因为它们可能是错误


但是请注意,使用ASP.NET后台工作可以随时中止(例如,当工作进程回收时)。您必须容忍突然消失的后台工作。在您的情况下,当用户尝试访问PDF时,PDF可能会丢失。此外,如果用户尝试下载PDF时仍在生成该PDF,该怎么办?必须解决这些问题。

如果您真的想使其异步,更简单的方法是在类中创建专用线程,在PGEGY-IIT上的线程将启动进程,然后在PGEYLoad完成。线程将使用Toel.Con()来等待,然后您将获得函数结果,但是正如所提到的,相对速度增益是最小的,考虑线程(或任务)确实是昂贵的

选项2
向返回pdf文件数据的通用处理程序创建一个ajax请求,这样就不涉及线程,而且用户体验更好

<%@ WebHandler Language="VB" Class="GetFile" %>

Imports System
Imports System.Web
Imports System.IO

Public Class GetFile : Implements IHttpHandler


    Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest        
        context.Response.Clear()        
            If File.Exists(filePath & docName) Then
                context.Response.AddHeader("content-disposition", "attachment; filename=" & HttpContext.Current.Server.UrlEncode(docName))
                context.Response.ContentType = "text/pdf"
                context.Response.WriteFile(filelocation & docName) 'in your case this writes the bites of the generated file, so instead of the path just pass in the data
            End If 
        context.Response.Flush()
        context.Response.End()
    End Sub

    Public ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
        Get
            Return False
        End Get
    End Property

End Class

导入系统
导入系统.Web
导入System.IO
公共类GetFile:实现IHttpHandler
Public Sub-ProcessRequest(ByVal上下文作为HttpContext)实现IHttpHandler.ProcessRequest
context.Response.Clear()
如果File.Exists(filePath和docName)存在,则
context.Response.AddHeader(“内容处置”、“附件;文件名=“&HttpContext.Current.Server.UrlEncode(docName))
context.Response.ContentType=“text/pdf”
context.Response.WriteFile(filelocation&docName)“”在您的例子中,它写入生成的文件的位,因此只传递数据而不是路径
如果结束
context.Response.Flush()
context.Response.End()
端接头
公共只读属性IsReusable()作为布尔值实现IHttpHandler.IsReusable
收到
返回错误
结束
端属性
末级
(不要使用下面的代码..有关推理,请参阅“答案”的末尾)

感谢所有人的帮助。最后我错了。我只需要创建一个异步包装函数来返回我的任务(字节())

如果我的初始代码是:

Function GetFileBytes() as Byte()
    Dim result() As Byte

      Using ms As New MemoryStream

        Dim reader As New PdfReader(pdfForm)
        Dim writer As New PdfStamper(reader, ms)

        Dim fields As AcroFields = writer.AcroFields

        fields.SetField("Customer Name", custInfo.FirstName + " " + custInfo.LastName)

        result = ms.GetBuffer
    End Using
End Function
现在,我创建了一个名为getFileByteAsync的新方法,用于返回Task(Of Byte()),调用上面描述的同一个GetFileBytes方法,它只是使用Task.Factory.StartNew调用,如下所示:

Public Shared Async Function GetFileBytesAsync() As Task(Of Byte())
        Dim t As Task(Of Byte()) = Task.Factory.StartNew(Function()
                                                             Return GetFileBytes()
                                                         End Function)

        Return Await t

    End Function
在我的调用函数中,我现在只使用任务对象的Result属性来访问字节数组。HTH

编辑:好的,正如Stephen Cleary恰当地指出的那样,我完全错了,不推荐使用上面的代码,也不异步执行任何操作。事实上,创建新线程是为了创建一些阻塞代码。对不起

我遇到过这样一个技术讲座:-这是如何使用异步构建ASP.NET Web应用程序。在54分钟的时候,它实际上表明尝试使用“后台线程”“在ASP.NET Web服务器上是错误的,因为IIS中没有可使用的后台线程,实际上您正在使用可以\应该用于响应Web请求的线程

下面是我的场景,想象一个网站在几页上收集数据,然后显示一个审查屏幕,然后让用户能够查看包含该数据的PDF。在review屏幕上,我需要生成一个1 MB的PDF文件,将其上载到BLOB存储,并在用户选择下载时使其可用

既然您提到了“blob存储”,我就假设您使用的是Azure

您需要一个工作者角色或服务来可靠地执行此操作。工作者角色应该只是从Azure队列读取数据并生成PDF


因此,当您的web角色在返回响应之前生成审查屏幕时,它还将把该数据放入Azure队列。当您的web角色收到用户接受审查的通知时,它应该(异步)等待,直到生成PDF文件。

如果您在页面事件的不同部分启动线程,则在页面开始时,在page_load上,您在page_LoadComplete上执行其他操作,您将获得等待线程的数据ThreadThank@Fabrizio,但鉴于我最近的编辑,我不希望使用这样的HTTPHandler。好吧,想象一下一个网站在几页上收集数据,然后显示一个审查屏幕,然后让用户能够查看包含该数据的PDF。在查看屏幕上,我需要生成一个1 MB的PDF文件,将其上载到BLOB存储,并使其可用