开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜