2011-04-20 141 views
1

我開發了一個基於長輪詢方法或Comet的實時打分應用程序,因爲他們也稱之爲。我已經使用在IIS 6上運行的ASP.NET 4.0(windows 2003 - 只有兩個CPU,這對池中線程的可用性沒有多大幫助)。在asp.net中處理.csv文件的異步http處理程序

數據以.csv格式顯示,粘貼到Web服務器上的源文件夾中,然後使用Microsoft JET 4.0 OleDb Provider導入並使用不同方法顯示,具體取決於應用程序的一部分。

長輪詢部分的引擎依賴於IHttpAsyncHandler.由於它是一個實時評分應用程序,用戶訪問網站,獲取當前數據的常規響應,並在body load上通過jquery ajax發送一個新請求給異步http處理程序。

該處理程序然後將請求存儲在隊列中,並且(通常)將該線程返回到線程池。一旦發生這種情況,我會創建一個手動重置事件,並保留該操作,同時創建一個文件系統觀察器對象併發送它以查找csv數據源文件夾中的更改。

一旦它觸發onChange事件,我設置手動重置事件,並允許異步操作恢復,獲取新的,刷新的csv文件並用新數據響應客戶端。

如果我一直沒有收到錯誤,這將會很好。一般來說,非常非常普遍的方式,應用程序正在工作,但我有一個問題,我不能很明確地指出。

也就是說,我不確定問題是否與訪問csv文件有關,因爲它們可能會被進入服務器的進程鎖定(ftp從運動場所轉移)。或者它可能是我的(ab)使用IHttpAsyncHandler,也可能只是我沒有足夠的CPU和線程(我很難相信,因爲我每天只有大約3000位獨立訪問者,噸知道小時數)。

是否有可能具有兩個CPU的IIS 6 Windows 2003不能支持這種類型的應用程序?

這裏就是我不斷收到錯誤:

事件類型:錯誤事件來源: ASP.NET 4.0.30319.0事件類別: 無事件ID:1325日期:20/04/2011 時間:15:33:14用戶:N/A計算機:xxx 說明:未處理的異常 發生,並且進程終止了 。

應用程序ID:/ LM/W3SVC/1/ROOT 進程ID:5264例外: System.Data.OleDb.OleDbException 消息:未指定的錯誤

堆棧跟蹤:在 System.Data.OleDb.OleDbConnectionInternal ..ctor(OleDbConnectionString 構造,OleDbConnection的連接)
在 System.Data.OleDb.OleDbConnectionFactory.CreateConnection(DbConnectionOptions 選項,對象poolGroupProviderInfo, 池類DBConnectionPool,的DbConnection owningOb ject) System.Data.ProviderBase.DbConnectionFactory。CreateNonPooledConnection(的DbConnection owningConnection, DbConnectionPoolGroup poolGroup)在 System.Data.ProviderBase.DbConnectionFactory.GetConnection(的DbConnection owningConnection)在 System.Data.ProviderBase.DbConnectionClosed.OpenConnection(的DbConnection outerConnection,DbConnectionFactory connectionFactory的)在 系統。 Data.OleDb.OleDbConnection.Open() 在Broker.brCSV.readCSV(字符串 文件名)在 SwatchTiming.AsynchOperation.StartAsyncTask(對象 workItemState)在 System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(對象 狀態)在 System.Threading.ExecutionContext.runTryCode(對象 的UserData)在 System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup在 System.Threading.ExecutionContext.RunInternal(ExecutionContext中 的ExecutionContext(TryCode 代碼,CleanupCode backoutCode,對象 的UserData), ContextCallback 回調在 System.Threading.ExecutionContext.Run(的ExecutionContext 的ExecutionContext,ContextCallback 回調,對象的狀態,對象的狀態),布爾 ignoreSyncCtx)在 System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem() 在 System.Threading.ThreadPoolWorkQueue.Dispatch() 在 System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()

而且也:

事件類型:錯誤事件來源:.NET運行時 4.0錯誤報告事件 類別:無事件ID:5000日期: 20/04/2011時間:15:33:14用戶: N/AComputer:xxx說明:EventType clr20r3,P1 w3wp.exe,P2 6.0。 3790 .3959,P3 45d6968e,P4 system.data,P5 4.0.0.0,P6 4ba1e064, P7 1ea3,P8 87,P9 system.data.oledb.oledbexception,P10 NIL。有關詳細信息,請參閱幫助 和支持中心 http://go.microsoft.com/fwlink/events.asp.Data:0000: 63 00 6C 00 72 00 32 00
clr2.0008:30 00 72 00 33 00 2C 00 0.r.3,0010:20 00 77 00 33 00 77 00 .w.3.w.0018:70 00 2e 00 65 00 78 00
p ... ex0020:65 00 2c 00 20 00 36 00 e。,。 .6.0028:2e 00 30 00 2e 00 33 00 ..0 ... 3.0030:37 00 39 00 30 00 2e 00 7.9.0 ... 0038:33 00 39 00 35 00 39 00 3.9.5.9.0040 :2c 00 20 00 34 00 35 00,。 .4.5.0048:64 00 36 00 39 00 36 00 d.6.9.6.0050:38 00 65 00 2c 00 20 00 8.e。,。 .0058:73 00 79 00 73 00 74 00 syst0060:65 00 6d 00 2e 00 64 00 em..d.0068:61 00 74 00 61 00 2c 00 ata,.0070:20 00 34 00 2e 00 30 00 .4 ... 0.0078:2e 00 30 00 2e 00 30 00
..0 ... 0.0080:2c 00 20 00 34 00 62 00 ,...。 .4.b.0088:61 00 31 00 65 00 30 00 a.1.e.0.0090:36 00 34 00 2c 00 20 00 6.4。,。 .0098:31 00 65 00 61 00 33 00 1.e.a.3.00a0:2c 00 20 00 38 00 37 00,。 .8.7.00a8:2c 00 20 00 73 00 79 00 ,。 .s.y.00b0:73 00 74 00 65 00 6d 00 s.t.e.m.00b8:2e 00 64 00 61 00 74 00 ..d.a.t。00c0:61 00 2e 00 6f 00 6c 00 a ... ol00c8:65 00 64 00 62 00 2e 00 edb..00d0:6f 00 6c 00 65 00 64 00 oled00d8:62 00 65 00 78 00 63 00 bexc00e0:65 00 70 00 74 00 69 00 epti00e8:6f 00 6e 00 20 00 4e 00 .N.00f0:49 00 00 4C 0D 0A 00 00 IL ....

和...

事件類型:錯誤事件來源:.NET運行時 事件類別:無事件ID: 1026日期:20/04/2011時間:15時34分26秒 用戶:N/A計算機:XXX 描述:應用程序:w3wp.exe的 Framework版本:v4.0.30319 說明:這個過程是 終止由於未處理 exception.Exception信息: System.Data.OleDb.OleDbException

堆棧:在 System.Data.ProviderBase.DbConnectionClosed.OpenConnection(System.Data.Common.DbConnection, System.Data.ProviderBase.DbConnectionFactory) 在 System.Data。 OleDb.OleDbConnection.Open() 在Broker.brCSV.readCSV在 [ProjectNamespace] .AsynchOperation.StartAsyncTask(System.Object的)(System.String) 在 System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(System.Object的) 在 System.Threading.ExecutionContext.runTryCode(System.Object) 在 System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode, CleanupCode,System.Object的)在 System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object的)在 System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object的,布爾值)在 System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem() 在 系統.Threading.ThreadPoolWorkQueue.Dispatch() at System.Threading._ThreadPoolWaitCallback.P erformWaitCallback()

最後幾條信息。我試圖微調IIS 6,但似乎沒有太多幫助。

因此,有沒有人有一個想法是什麼,以及爲什麼我的網站每五分鐘崩潰?

編輯:這是我在處理程序代碼,希望這有助於

BeginProcessRequest如下(比我只設置IsReusable爲false等):

Public Function BeginProcessRequest(_ 
    ByVal context As System.Web.HttpContext, _ 
    ByVal cb As System.AsyncCallback, _ 
    ByVal extraData As Object) _ 
    As System.IAsyncResult _ 
    Implements System.Web.IHttpAsyncHandler.BeginProcessRequest 

    Dim asynch As New AsynchOperation(cb, context, extraData) 
    asynch.StartAsyncWork() 

    Return asynch 
End Function 

,然後::

Class AsynchOperation 
Implements IAsyncResult 
Private _completed As Boolean 
Private _state As [Object] 
Private _callback As AsyncCallback 
Private _context As HttpContext 
Private mre As New ManualResetEvent(False) 
Dim br As New Broker.brCSV 
Dim brLiveGames As New Broker.brLiveGames 

ReadOnly Property IsCompleted() As Boolean _ 
     Implements IAsyncResult.IsCompleted 
    Get 
     Return _completed 
    End Get 
End Property 

ReadOnly Property AsyncWaitHandle() As WaitHandle _ 
     Implements IAsyncResult.AsyncWaitHandle 
    Get 
     Return Nothing 
    End Get 
End Property 

ReadOnly Property AsyncState() As [Object] _ 
     Implements IAsyncResult.AsyncState 
    Get 
     Return _state 
    End Get 
End Property 

ReadOnly Property CompletedSynchronously() As Boolean _ 
     Implements IAsyncResult.CompletedSynchronously 
    Get 
     Return False 
    End Get 
End Property 

Public Sub New(ByVal callback As AsyncCallback, _ 
     ByVal context As HttpContext, _ 
     ByVal state As [Object]) 
    _callback = callback 
    _context = context 
    _state = state 
    _completed = False 
End Sub 

Public Sub StartAsyncWork() 
    ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf StartAsyncTask), Nothing) 
End Sub 

Private Sub StartAsyncTask(ByVal workItemState As [Object]) 


    Dim fsw As New FileSystemWatcher("D:\ClientRoot\Swatchtiming\bv\ReadData\") 
    fsw.NotifyFilter = NotifyFilters.LastWrite 
    AddHandler fsw.Changed, AddressOf OnChanged 
    fsw.EnableRaisingEvents = True 
    fsw.IncludeSubdirectories = False 

    Dim aTimer As New System.Timers.Timer 
    AddHandler aTimer.Elapsed, AddressOf OnTimerChanged 
    aTimer.Interval = 60000 
    aTimer.Enabled = True 
    mre.WaitOne() 

    Dim rdr As OleDbDataReader 
    Dim i As Integer = 0 
    Dim eventName As String = "" 
    Dim dsFiles As DataSet = brLiveGames.getFileNameWithEventTitle() 
    Dim teamClass As String = "TeamA" 
    Dim serveIndicator As String = "" 
    Dim serveImage As String = "" 
    Dim serveSpeed As String = "" 
    Dim fileName As String = "" 
    Dim fileNumber As String = "" 
    Dim matchID As String = "" 
    Dim venueLocation As String = "" 
    Dim set1, set2, set3 As String 

    For i = 0 To Convert.ToInt16(dsFiles.Tables(0).Rows.Count) - 1 
     If eventName <> dsFiles.Tables(0).Rows(i).Item("EventTitle") Then 
      eventName = dsFiles.Tables(0).Rows(i).Item("EventTitle") 
      _context.Response.Write("<div class='eventTitle'>" & eventName.ToString() & " <span class='bracketLink'>- <a href='Brackets.aspx?Brackets=" & dsFiles.Tables(0).Rows(0).Item("BracketsFile") & "'>View brackets</a></span></div>") 
     End If 
     rdr = br.readCSV(dsFiles.Tables(0).Rows(i).Item("fileName")) 

     _context.Response.Write("<div class='matchView'>") 
     While (rdr.Read) 
      matchID = rdr.Item("Current_Match_Index") 
      If venueLocation <> "" Then 
       venueLocation = "" 
      Else 
       venueLocation = br.getVenueLocation(matchID) 
       _context.Response.Write("<div class='matchTitle'>" + venueLocation + "</div>") 
      End If 
      set1 = IIf(IsDBNull(rdr.Item("SET_1")), "&nbsp;", rdr.Item("SET_1")) 
      set2 = IIf(IsDBNull(rdr.Item("SET_2")), "&nbsp;", rdr.Item("SET_2")) 
      set3 = IIf(IsDBNull(rdr.Item("SET_3")), "&nbsp;", rdr.Item("SET_3")) 
      _context.Response.Write("<div class='" & teamClass & "'>") 
      If teamClass <> "TeamB" Then 
       teamClass = "TeamB" 
      Else 
       teamClass = "TeamA" 
      End If 
      serveIndicator = IIf(IsDBNull(rdr.Item("Service_Indicator")), "", rdr.Item("Service_Indicator")) 
      If serveIndicator = "" Then 
       serveImage = "<img src='images/css/serveIndicatorNone.png' alt='#' width='14' height='14' />" 
      Else 
       serveImage = "<img src='images/css/serveIndicator.png' alt='#' width='14' height='14' />" 
      End If 
      serveSpeed = IIf(IsDBNull(rdr.Item("Serve_Speed")), "&nbsp;", "Serve: " & rdr.Item("Serve_Speed") & " km/h") 
      _context.Response.Write("<div class='flag'><img src='images/flags/" & rdr.Item("NOC") & ".jpg' alt='" & rdr.Item("NOC") & "' width='22' height='14' /></div><div class='NOC'>" & rdr.Item("NOC") & "</div><div class='serveIndicator'>" & serveImage & "</div><div class='teamName'>" & rdr.Item("Short_Team_Name") & "</div><div class='set1'>" & set1 & "</div><div class='set2'>" & set2 & "</div><div class='set3'>" & set3 & "</div><div class='serveSpeed'>" & serveSpeed & "</div>") 
      _context.Response.Write("</div>") 
     End While 
     _context.Response.Write("</div>") 
     rdr.Close() 
    Next 
    fsw.Dispose() 
    dsFiles.Dispose() 
    _context.Response.End() 

    _completed = True 
    _callback(Me) 

End Sub 

Private Sub OnChanged(ByVal sender As Object, ByVal e As FileSystemEventArgs) 
    mre.Set() 
End Sub 

Private Sub OnTimerChanged(ByVal sender As Object, ByVal e As ElapsedEventArgs) 
    mre.Set() 
End Sub 

End Class 

編輯#2:用於Broker.brCSV.readCSV(文件名)的代碼

Public Function readCSV(ByVal fileName As String) As OleDbDataReader 
    Dim rdr As OleDbDataReader = Nothing 
    Dim folderName = ("FolderName") 
    Dim cnString As String = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & folderName & ";Extended Properties='text;HDR=Yes;FMT=Delimited';Mode=3" 

    Dim cn As New OleDb.OleDbConnection(cnString) 
    Dim cm As New OleDb.OleDbCommand("Select * from " & fileName, cn) 
    cm.Connection.Open() 
    rdr = cm.ExecuteReader(System.Data.CommandBehavior.CloseConnection) 

    Return rdr 
End Function 

請注意連接字符串的結束,特別是Mode參數。 msdn指出,這是您如何指定文件訪問權限,但可能是因爲我沒有以正確的方式解釋指令......即,mode=3應該指定文件訪問爲讀/寫,但我是不知道它是否有效。

編輯#3:新Broker.brCSV.readCSV()引發InvalidOperationException

按照那種幫手Smudge202我已經改變了Broker.brCSV.readCSV方法的代碼的建議如下:

Public Function readCSV(ByVal fileName As String) As OleDbDataReader 
    Dim folderName = ("Folder Name") 
    Dim cnString As String = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & folderName & ";Extended Properties='text;HDR=Yes;FMT=Delimited';Mode=3" 

    Using cn As New OleDb.OleDbConnection(cnString) 
     Using cm As New OleDb.OleDbCommand("Select * from " & fileName, cn) 
      cm.Connection.Open() 
      Dim rdr As OleDbDataReader = cm.ExecuteReader(System.Data.CommandBehavior.CloseConnection) 
      Return rdr 
     End Using 
    End Using 

End Function 

然而,測試時這些代碼引起以下錯誤:

事件類型:錯誤 事件來源:ASP.NET 4.0 .30319.0 事件類別:無 事件ID:1325 日期:22/04/2011 時間:8點46分33秒 用戶:N/A 計算機:EUW0002184 描述: 未處理的異常發生,並且該過程是終止。

應用程序ID:/ LM/W3SVC/1/ROOT

進程ID:6408

異常:System.InvalidOperationException

消息:無效試圖調用讀取時讀取器被關閉。

堆棧跟蹤:在System.Data.OleDb.OleDbDataReader.Read() 在SwatchTiming.AsynchOperation.StartAsyncTask(對象workItemState) 在System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(對象狀態) 在System.Threading.ExecutionContext。 runTryCode(對象的UserData) 在System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode代碼,CleanupCode backoutCode,對象的UserData) 在System.Threading.ExecutionContext.RunInternal(的ExecutionContext的ExecutionContext,ContextCallback回調,對象狀態) 在的System.Threading .ExecutionContext.Run(ExecutionContext executionContext,ContextCallback回調,對象狀態,布爾ignoreSyncCtx) 在System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem。ExecuteWorkItem() 在System.Threading.ThreadPoolWorkQueue.Dispatch() 在System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()

還有:

事件類型:錯誤 事件來源:.NET運行 事件類別:無 事件ID:1026 日期:22/04/2011 時間:8時47分53秒 用戶:N/A 計算機:EUW0002184 說明: 應用程序:w3wp.exe的 Framework版本:v4.0.30319 描述:由於未處理的異常而終止該進程。 異常信息信息:System.InvalidOperationException 堆棧: 在System.Data.OleDb.OleDbDataReader.Read() 在SwatchTiming.AsynchOperation.StartAsyncTask(System.Object的) 在System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(System.Object的) 在系統.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext,系統。)System.Threading.ExecutionContext.runTryCode(System.Object) 在System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode,CleanupCode,System.Object) (System.Threading.ExecutionContext,System.Threading.ContextCallback,System.Object,Boolean) 在System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem() 在System.Threading.ThreadPoolWorkQueue.Dispatch() 在System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()

所以,當處理程序試圖使用新的readCSV方法我得到這些錯誤...任何進一步的建議? :)謝謝塗抹,謝謝其他人!

+0

你的異常的堆棧跟蹤,似乎在OLEDB提供程序予以指點,我相信這是你用來讀取傳入的CSV文件的供應商?您在什麼階段從CSV文件中獲取數據?從你的描述中可以看出,有幾個線程試圖同時使用提供程序,這會導致提供程序中出現IoException異常(儘管我希望在棧跟蹤中看到這種說法是誠實的)。另外,(請原諒冗長的評論),IHttpAsyncHandler的等待句柄持有的線程在接收到信號時仍然存在? (超時?) – Smudge202 2011-04-20 19:08:27

+0

@ Smudge202 謝謝您的回覆塗抹。一旦文件系統觀察者注意到源文件夾中的更改,我將獲取數據。我將編輯我的文章,以便我可以添加代碼,以便您可以仔細查看它,如果您願意......再次感謝! – pzelenovic 2011-04-20 21:30:45

+0

感謝您添加您的代碼。您是否也可以添加「Broker.brCSV.readCSV(String fileName)」的代碼,這是您在StartAsyncTask中調用的導致問題的函數(請參閱stacktrace)。夫婦多點。循環不需要轉換爲Int16,Rows.Count已經是一個整數。此外,您可以完全清除計時器並使用重載的mre.WaitOne(msTimeout)。將它與Dim filesChanged組合爲Boolean = mre.WaitOne(60000)來確定文件是否確實發生了變化? – Smudge202 2011-04-21 08:26:33

回答

1

除了一個兩個評論到目前爲止我已經添加了.... =)

,正如你在第3編輯已經注意到,一旦讀者已經設置,您將無法取回來自它的數據。

這個想法是你創建並打開你的連接。連接打開時儘可能早地獲取數據,然後處理一旦獲得數據後使用的所有資源。

在你的情況下,你打開和關閉readCSV函數內的連接,然後將封閉的閱讀器傳遞迴「StartAsyncTask」。你也許可以做的是輕微的重構...而不是使用OleDbDataReader你可以使用OleDbDataAdapter。使用適配器,您可以調用Fill method來填充數據集。

一旦數據集被填充,它就在內存中。您可以關閉適配器,關閉連接,處理這兩個('使用'語句)並將數據集傳遞迴StartAsync方法?

評論這裏如果你需要任何這樣的例子。

祝你好運!

編輯:

關於您正在進行的多線程工作的簡要說明...

關於IIS設置,如果你是在一個以上的進程中運行你的網站要知道,在某個階段,你將可能有2個進程(或更多)坐着等待文件系統觀察。當FSW檢測到更改時,它會通知您的兩個過程;以不可預知的順序,但可能會快速連續,這反過來會導致兩個獨立的線程開始讀取文件。您可以在此階段遇到問題時,兩個線程請求Jet提供在同一時間打開相同的文件(S)。確保你有足夠的異常捕獲邏輯來幫助。

如果您遇到這種情況,您甚至可能需要考慮使用mutexes,以便一次允許一個進程處理結果,但我很少鼓勵這些進程。

關於線程異常的說明,請看看this article,我相信在IIS7.5/.Net中仍然適用。4.對於工作線程要非常小心,如果沒有捕獲,異常可能會使網站失效。

+0

感謝您的持續支持。我希望你至少得到一些精神上的滿足:)無論如何,關於IIS設置,我沒有啓用應用程序使用兩個進程(它被稱爲我想的網絡花園)。通過文件訪問的初始問題(以及「另一個進程已經鎖定文件」的信息)進行教導,如果我只啓用運行應用程序的多個進程,則同樣的事情可能會發生,這對我來說是合乎邏輯的。我準備了一個2.0版本的建議,並會在今晚進行測試。我會讓你知道它是如何解決的... – pzelenovic 2011-04-22 14:23:19

+0

除此之外,有趣的是,在另一個操作中,我確實使用了oledbdataadapter,但不是基本的一個......當然,這部分應用程序從來沒有造成我任何問題:)因此我的暱稱,我猜... – pzelenovic 2011-04-22 14:24:53

+0

哈哈,至少你已經有了使用適配器的所有模板代碼。糾正Web花園筆記,如果您需要這種方法,我會建議將FSW代碼刪除並放入WCF服務中,以允許單個OOP進程管理這些文件。和以前一樣,祝你好運。 – Smudge202 2011-04-22 14:38:00