Prevent thread from being blocked too long in .Net
I have a .Net windows service. This hosts a WCF service, and a number of "Simulations" that run in separate threads... each simulation has been setup so it's very serial in action to prevent too many threads in use at once. I have a number of Thread.Sleep(100) calls where I'd expect to have not too much of an issue. However, there are times after running for a few minutes where the thread will literally freeze for up to 30 seconds on a slow machine. I've made a few tweaks, and it now happens a bit less frequently, and on my local machine it will only freeze for 4-7 seconds, but this is too much for the user experience expected. Client messages are expected to be no more than 2 seconds from availability.
I'm already setting the thread's priority to "Highest" which is what got it down as far as it did, and isn't happening at any specific code block. Any other suggestions? I could setup a thread pool and/or run all operations as pooled expressions from a single manager thread over all simulations. However, this already happens with a single thread running in a dev environment. I really don't want to go through the development time to refactor this area of code without knowing it will resolve my issue at hand.
Public Sub StartSim()
Log.Info("SimulationInstance.StartSim", String.Format("Starting the simulation instance: {0}", InstanceEntity.Guid), Nothing)
'initialize thread, and start it
SyncLock _lock
If _runner IsNot Nothing Then
Return 'running
End If
_runner = New Thread(New ThreadStart(AddressOf RunSimulation))
_runner.Priority = ThreadPriority.Highest
_runner.Start()
End SyncLock
End Sub
Private Sub RunSimulation()
Me.StartedOn = DateTime.Now
Me.StartedOnMinutes = TimeSpan.FromMinutes(InstanceEntity.MinutesTaken)
InstanceEntity.StartedOn = Me.StartedOn
TranscriptLog.AppendTranscriptLog(
DB,
InstanceEntity.Guid,
Guid.Empty,
InstanceEntity.Scenario,
"Simulation instance started.",
"from",
"to",
"Simulation instance started.",
"entry",
InGameTime,
"event",
Nothing,
0,
""
)
While True
Try
' This is the master simulation controller
RunSimulation_HandleMessages()
RunSimulation_CheckPulse()
RunSimulation_IdleCheck()
RunSimulation_ServiceUnits()
RunSimulation_AutoSave()
Catch ex As ThreadAbortException
'closing
Log.Info("SimulationInstance.RunSimulation", "Ending Simulation", String.Empty)
TranscriptLog.AppendTranscriptLog(
DB,
InstanceEntity.Guid,
Guid.Empty,
InstanceEntity.Scenario,
"Simulation instance stopped.",
"from",
"to",
"Simulation instance stopped.",
"entry",
InGameTime,
"event",
Nothing,
0,
""
)
SaveSim()
Return ' done running
Catch ex As Exception
Log.Critical("SimulationInstance.RunSimulation", "Critical Error", ex.ToString())
Dim dialog = <dialog>
<title>Server Internal Error</title>
<image>dialog_idle.png</image>
<message><%= New XCData(String.Format("<p><b>开发者_运维技巧;Server Error:</b></p><p><hr>{0}<hr></p><p>Terminating the simulation.</p><p>Please try again.</p>", ex.Message)) %></message>
<buttons>
<button action="exit">Exit</button>
</buttons>
</dialog>
BroadcastMessage("dialog", "IMAGE+TEXT", Nothing, Guid.NewGuid().ToString(), dialog)
StopSim()
Return 'done running
End Try
End While
End Sub
Yeah, it's VB (not my choice, but I get XML literals). Each of the RunSimulation_*() methods is well behaved, and does have proper sleeps... What I don't expect is to be frozen for 4+ seconds every 3-6 minutes on places where I haven't explicitly given a sleep, on a with only one instance running on a core i5 (quad core). This would be horrible for the user experience and I've been pulling my hair out for a few hours now.
精彩评论