在 asp.net 中处理 .csv 文件的异步 http 处理程序
我开发了一个实时评分应用程序,它基于长轮询方法,或者他们也称之为彗星。我使用了在 IIS 6 上运行的 ASP.NET 4.0(Windows 2003 - 只有两个 CPU,这对池中线程的可用性没有太大帮助)。
数据以 .csv
文件的形式出现,这些文件被粘贴到 Web 服务器上的源文件夹中,然后我使用 Microsoft JET 4.0 OleDb Provider 导入该文件,并使用不同的方法进行显示,取决于应用程序的部分。
长轮询部分的引擎依赖于 IHttpAsyncHandler。
由于它是一个实时评分应用程序,因此用户访问网站,获得包含当前数据的定期响应,并在正文加载时通过以下方式发送新请求: jquery ajax 到异步 http 处理程序。
然后,该处理程序将请求存储在队列中,并(通常)将线程返回到线程池。一旦发生这种情况,我将创建一个手动重置事件,并保留该操作,同时创建并发送一个文件系统观察程序对象以查找 csv 数据源文件夹中的更改。
一旦它触发 onChange
事件,我就会设置手动重置事件,并且允许异步操作恢复以获取新的、刷新的 csv 文件,并使用新数据响应客户端。
如果我不总是出现错误,那就太好了。一般来说,非常非常一般的方式,应用程序正在工作,但我有一个我不能完全指出的问题。
也就是说,我不确定问题是否在于访问 csv 文件,因为它们可能被将它们带入服务器的进程锁定(从体育场馆进行 ftp 传输)。或者可能是我(滥用)使用了 IHttpAsyncHandler
,或者只是因为我没有足够的 CPU 和线程(我很难相信,因为我只有大约 3000 个独特的 CPU 和线程)每天都有访客。我不知道每小时的人数)。
具有两个 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 constr, OleDbConnection 连接)
在 System.Data.OleDb.OleDbConnectionFactory.CreateConnection(DbConnectionOptions 选项,对象池GroupProviderInfo, DbConnectionPool 池、DbConnection 拥有对象)在 System.Data.ProviderBase.DbConnectionFactory.CreateNonPooledConnection(DbConnection 拥有连接, DbConnectionPoolGroup (池组) at System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection 拥有连接)位于 System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection 外部连接、DbConnectionFactory 连接工厂)位于 System.Data.OleDb.OleDbConnection.Open() 在 Broker.brCSV.readCSV(字符串 文件名)位于 SwatchTiming.AsynchOperation.StartAsyncTask(对象 工作项状态)在 System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(对象 状态)在 System.Threading.ExecutionContext.runTryCode(对象 用户数据)位于 System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode 代码、CleanupCode backoutCode、对象 用户数据)位于 System.Threading.ExecutionContext.RunInternal(ExecutionContext 执行上下文、上下文回调 回调,对象状态)位于 System.Threading.ExecutionContext.Run(ExecutionContext 执行上下文、上下文回调 回调、对象状态、布尔值 忽略SyncCtx)在 System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem() 在 System.Threading.ThreadPoolWorkQueue.Dispatch() 在 System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()
还有:
事件类型:错误事件源:.NET 运行时 4.0 错误报告事件 类别:无 事件 ID:5000 日期: 2011年4月20日 时间:15:33:14 用户: N/A计算机:xxx 说明:事件类型 clr20r3,P1 w3wp.exe,P2 6.0.3790.3959、P3 45d6968e、P4 系统数据、P5 4.0.0.0、P6 4ba1e064、 P7 1ea3、P8 87、P9 系统.data.oledb.oledb异常,P10 零。有关详细信息,请参阅帮助 和支持中心位于 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 系统0060: 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.ea3.00a0: 2c 00 20 00 38 00 37 00 ,. .8.7.00a8:2c 00 20 00 73 00 79 00 ,. .sy00b0: 73 00 74 00 65 00 6d 00 茎00b8: 2e 00 64 00 61 00 74 00 ..dat00c0: 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 4c 00 0d 00 0a 00 伊利诺伊州....
和……
事件类型:错误事件源:.NET 运行时事件类别:无事件 ID: 1026 日期:2011年4月20日 时间:15:34:26 用户: N/A 计算机: xxx 描述:应用程序: w3wp.exe 框架版本:v4.0.30319 描述:该过程是 由于未处理而终止 异常信息: System.Data.OleDb.OleDbException
堆栈:位于 System.Data.ProviderBase.DbConnectionClosed.OpenConnection(System.Data.Common.DbConnection, 系统.Data.ProviderBase.DbConnectionFactory) 在 System.Data.OleDb.OleDbConnection.Open() 在 Broker.brCSV.readCSV(System.String) 在 [项目命名空间].AsynchOperation.StartAsyncTask(System.Object) 在 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, 系统.Threading.ContextCallback, 系统.对象)位于 System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, 系统.Threading.ContextCallback, System.Object,布尔值)位于 System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem() 在 System.Threading.ThreadPoolWorkQueue.Dispatch() 在 System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()
最后还有一些信息。我尝试过对 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
然后是实现 IAsyncResult
的 AsynchOperation
类:
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")), " ", rdr.Item("SET_1"))
set2 = IIf(IsDBNull(rdr.Item("SET_2")), " ", rdr.Item("SET_2"))
set3 = IIf(IsDBNull(rdr.Item("SET_3")), " ", 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")), " ", "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(fileName) 的代码
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 日期:2011年4月22日 时间:08:46:33 用户:不适用 计算机:EUW0002184 描述: 发生未处理的异常,进程被终止。
应用程序 ID:/LM/W3SVC/1/ROOT
进程 ID:6408
异常:System.InvalidOperationException
消息:阅读器关闭时调用 Read 的尝试无效。
StackTrace:位于 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(ExecutionContextexecutionContext,ContextCallback 回调,对象状态) 在System.Threading.ExecutionContext.Run(ExecutionContextexecutionContext,ContextCallback回调,对象状态,布尔ignoreSyncCtx) 在 System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem() 在 System.Threading.ThreadPoolWorkQueue.Dispatch() 在 System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()
以及:
事件类型:错误 事件源:.NET 运行时 活动类别:无 事件ID:1026 日期:2011年4月22日 时间:08:47:53 用户:不适用 计算机:EUW0002184 描述: 应用程序: w3wp.exe 框架版本:v4.0.30319 描述:由于未处理的异常,进程被终止。 异常信息:System.InvalidOperationException 堆: 在 System.Data.OleDb.OleDbDataReader.Read() 在 SwatchTiming.AsynchOperation.StartAsyncTask(System.Object) 在 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() 在 System.Threading.ThreadPoolWorkQueue.Dispatch() 在 System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()
因此,当处理程序尝试使用新的 readCSV 方法时,我收到这些错误...还有其他建议吗? :) 谢谢 Smudge,也谢谢其他人!
I have developed a live scoring application which is based on the long polling approach, or Comet as they also call it. I have used ASP.NET 4.0 running on IIS 6 (windows 2003 - only two CPUs, which does not help me much with the availability of threads in the pool).
The data is coming in in the form of .csv
files that are pasted to the source folder on the web server, which I then import with the use of Microsoft JET 4.0 OleDb Provider, and display utilizing different methods, depending on the part of the application.
The engine of the long polling part relies on the IHttpAsyncHandler.
Since it is a live scoring application, the user visits the website, gets a regular response with current data, and on body load sends a new request via jquery ajax to the asynchronous http handler.
This handler then stores the request in the queue, and returns (normally) the thread back to the thread pool. Once this happens, I create a manual reset event, and hold the operation, while a file system watcher object is created and sent to look for changes in the csv data source folder.
Once it fires an onChange
event I set the manual reset event and the async operation is permitted to resume with getting the new, refreshed csv files and to respond to the client with fresh data.
This would all be nice if I was not getting errors all the time. In general, very very general way, the application is working, but I have a problem which I cannot quite pin point.
Namely, I am not sure whether the problem is with access to the csv files as they might be locked by the process which brings them in to the server (ftp transfer from the sport venue). Or is it maybe my (ab)use of the IHttpAsyncHandler
, or maybe it is just that I don't have enough CPUs and threads (which I find hard to believe, as I have only around 3000 unique visitors every day. I don't know the hour by hour numbers).
Is it possible that a IIS 6 windows 2003 with two CPUs cannot upholad this sort of an application?
here's the errors that I keep getting:
Event Type: Error Event Source:
ASP.NET 4.0.30319.0 Event Category:
None Event ID: 1325 Date: 20/04/2011
Time: 15:33:14 User: N/A Computer: xxx
Description:An unhandled exception
occurred and the process was
terminated.Application ID: /LM/W3SVC/1/ROOT
Process ID: 5264 Exception:
System.Data.OleDb.OleDbException
Message: Unspecified errorStackTrace: at
System.Data.OleDb.OleDbConnectionInternal..ctor(OleDbConnectionString
constr, OleDbConnection connection)
at
System.Data.OleDb.OleDbConnectionFactory.CreateConnection(DbConnectionOptions
options, Object poolGroupProviderInfo,
DbConnectionPool pool, DbConnection
owningObject) at
System.Data.ProviderBase.DbConnectionFactory.CreateNonPooledConnection(DbConnection
owningConnection,
DbConnectionPoolGroup poolGroup) at
System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection
owningConnection) at
System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection
outerConnection, DbConnectionFactory
connectionFactory) at
System.Data.OleDb.OleDbConnection.Open()
at Broker.brCSV.readCSV(String
fileName) at
SwatchTiming.AsynchOperation.StartAsyncTask(Object
workItemState) at
System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(Object
state) at
System.Threading.ExecutionContext.runTryCode(Object
userData) at
System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode
code, CleanupCode backoutCode, Object
userData) at
System.Threading.ExecutionContext.RunInternal(ExecutionContext
executionContext, ContextCallback
callback, Object state) at
System.Threading.ExecutionContext.Run(ExecutionContext
executionContext, ContextCallback
callback, Object state, Boolean
ignoreSyncCtx) at
System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
at
System.Threading.ThreadPoolWorkQueue.Dispatch()
at
System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()
And also:
Event Type: Error Event Source: .NET
Runtime 4.0 Error Reporting Event
Category: None Event ID: 5000 Date:
20/04/2011 Time: 15:33:14 User:
N/AComputer: xxx Description: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. For more information, see Help
and Support Center at
http://go.microsoft.com/fwlink/events.asp.Data:0000:
63 00 6c 00 72 00 32 00
c.l.r.2.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...e.x.0020: 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 s.y.s.t.0060: 65 00 6d 00 2e 00 64 00
e.m...d.0068: 61 00 74 00 61 00 2c 00
a.t.a.,.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...o.l.00c8: 65 00 64 00 62 00 2e 00
e.d.b...00d0: 6f 00 6c 00 65 00 64 00
o.l.e.d.00d8: 62 00 65 00 78 00 63 00
b.e.x.c.00e0: 65 00 70 00 74 00 69 00
e.p.t.i.00e8: 6f 00 6e 00 20 00 4e 00
o.n. .N.00f0: 49 00 4c 00 0d 00 0a 00
I.L.....
and...
Event Type: Error Event Source: .NET
Runtime Event Category: None Event ID:
1026 Date: 20/04/2011 Time: 15:34:26
User: N/A Computer: xxx
Description:Application: w3wp.exe
Framework Version: v4.0.30319
Description: The process was
terminated due to an unhandled
exception.Exception Info:
System.Data.OleDb.OleDbExceptionStack: at
System.Data.ProviderBase.DbConnectionClosed.OpenConnection(System.Data.Common.DbConnection,
System.Data.ProviderBase.DbConnectionFactory)
at
System.Data.OleDb.OleDbConnection.Open()
at Broker.brCSV.readCSV(System.String)
at
[ProjectNamespace].AsynchOperation.StartAsyncTask(System.Object)
at
System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(System.Object)
at
System.Threading.ExecutionContext.runTryCode(System.Object)
at
System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode,
CleanupCode, System.Object) at
System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext,
System.Threading.ContextCallback,
System.Object) at
System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext,
System.Threading.ContextCallback,
System.Object, Boolean) at
System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
at
System.Threading.ThreadPoolWorkQueue.Dispatch()
at
System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()
A few more pieces of info for the end. I have tried to fine tune the IIS 6 but it did not seem to help out too much.
So does anybody have an idea what the heck is going on, and why my site is crashing every five minutes?
EDIT: Here's my code in the handler, hope this helps
The BeginProcessRequest
is as follows (other than that I am only setting the IsReusable
to 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
and then the AsynchOperation
class which implements IAsyncResult
:
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")), " ", rdr.Item("SET_1"))
set2 = IIf(IsDBNull(rdr.Item("SET_2")), " ", rdr.Item("SET_2"))
set3 = IIf(IsDBNull(rdr.Item("SET_3")), " ", 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")), " ", "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
Edit #2: The code for the Broker.brCSV.readCSV(fileName)
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
Please observe the ending of the connection string, specifically the Mode
parameter. The msdn states that this is how you specify the file access permissions, but it could be that I did not interpret the instructions in the right way... Namely, mode=3
is supposed to specify the file access as read/write but I'm not sure if it works.
EDIT #3: The new Broker.brCSV.readCSV() throws an InvalidOperationException
As per the suggestions of the kind helper Smudge202 I have altered the code of the Broker.brCSV.readCSV method as follows:
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
However, when tested this code caused the following errors:
Event Type: Error
Event Source: ASP.NET 4.0.30319.0
Event Category: None
Event ID: 1325
Date: 22/04/2011
Time: 08:46:33
User: N/A
Computer: EUW0002184
Description:
An unhandled exception occurred and the process was terminated.
Application ID: /LM/W3SVC/1/ROOT
Process ID: 6408
Exception: System.InvalidOperationException
Message: Invalid attempt to call Read when reader is closed.
StackTrace: at System.Data.OleDb.OleDbDataReader.Read()
at SwatchTiming.AsynchOperation.StartAsyncTask(Object workItemState)
at System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(Object state)
at System.Threading.ExecutionContext.runTryCode(Object userData)
at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
at System.Threading.ThreadPoolWorkQueue.Dispatch()
at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()
as well as:
Event Type: Error
Event Source: .NET Runtime
Event Category: None
Event ID: 1026
Date: 22/04/2011
Time: 08:47:53
User: N/A
Computer: EUW0002184
Description:
Application: w3wp.exe
Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.InvalidOperationException
Stack:
at System.Data.OleDb.OleDbDataReader.Read()
at SwatchTiming.AsynchOperation.StartAsyncTask(System.Object)
at System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(System.Object)
at System.Threading.ExecutionContext.runTryCode(System.Object)
at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode, CleanupCode, System.Object)
at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)
at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
at System.Threading.ThreadPoolWorkQueue.Dispatch()
at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()
So, when the handler attempts to use the new readCSV method I get these errors... Any further suggestions? :) Thank you Smudge, and thanks everyone else!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
除了到目前为止我添加的一两条评论之外......=)
正如您在第三次编辑中注意到的那样,一旦阅读器被处理掉,您就无法从中获取数据。
这个想法是您创建并打开您的连接。连接打开时尽早获取数据,然后在获得数据后处理使用过的所有资源。
在您的情况下,您将在 readCSV 函数中打开和关闭连接,然后将关闭的读取器传递回“StartAsyncTask”。也许您可以做的是稍微重构...而不是使用 OleDbDataReader 您可以使用 OleDbDataAdapter。使用适配器,您可以调用Fill 方法来填充数据集。
一旦数据集被填充,它就在内存中。您可以关闭适配器、关闭连接、处理这两个语句(“using”语句)并将数据集传递回 StartAsync 方法吗?
如果您需要任何此类示例,请在此处发表评论。
祝你好运!
编辑:
关于您正在做的多线程工作的快速说明...
关于 IIS 设置,如果您在多个进程上运行您的网站,请注意在某个阶段您可能会有 2 个进程(或更多)等待文件系统观察者。当 FSW 检测到更改时,它会通知您的两个进程;以不可预测的顺序,但可能会快速连续,这反过来将导致两个单独的线程开始读取文件。当两个线程请求 Jet Provider 同时打开相同的文件时,您可能在此阶段遇到问题。确保这里有足够的异常捕获逻辑来提供帮助。
您甚至可能需要考虑使用互斥体,如果对于您来说就是这种情况,一次允许一个过程来处理结果,但我很少鼓励这样做。
关于线程异常的说明,请查看这篇文章,我相信它在 IIS7 中仍然适用.5/.Net 4. 对工作线程要非常小心,如果不捕获异常,可能会导致网站瘫痪。
In addition to one or two comments I've added so far.... =)
As you've noticed in your 3rd edit, once a reader has been disposed, you are unable to fetch the data from it.
The idea is that you create and open your connection. Fetch the data as early as possible when the connection is open, and then dispose any resources that were used once you have the data.
In your case, you are opening and closing the connection within the readCSV function, then passing the closed reader back to "StartAsyncTask". What you could do perhaps, is slightly refactor... Instead of using the OleDbDataReader you could use an OleDbDataAdapter. Using the adapter you can call the Fill method to populate a dataset.
Once a dataset has been populated, it is in memory. You can close the adapter, close the connection, dispose of both ('using' statements) and pass the dataset back to your StartAsync method?
Comment on here if you need any examples of this.
Good luck!
EDIT:
A quick note on the multithreading work you're doing...
Regarding the IIS settings, if you are running your website on more than one process be aware that at some stage you will likely have 2 processes (or more) sat awaiting the file system watcher. When the FSW detects a change it will notify both of your processes; in an unpredictable order, but likely in quick succession, which in turn will cause two seperate threads to start reading the files. You may encounter issues at this stage when two threads request the Jet Provider to open the same file(s) at the same time. Ensure you have plenty of exception catching logic in here to help.
You might even need to consider the use of mutexes if this is the case for you, to allow one process at a time to process results, but I rarely like to encourage those.
On the note of thread exceptions, take a look at this article which I believe still holds true in IIS7.5/.Net 4. Be very careful with your worker threads, exceptions can take down the website if not caught.