private void WorkLoop() { try { Time = Stopwatch.ElapsedMilliseconds; long conTime = Time; long saveTime = Time + Settings.SaveDelay * Settings.Minute; long userTime = Time + Settings.Minute * 5; long processTime = Time + 1000; long StartTime = Time; int processCount = 0; int processRealCount = 0; LinkedListNode<MapObject> current = null; if (Settings.Multithreaded) { for (int j = 0; j < MobThreads.Length; j++) { MobThreads[j] = new MobThread(); MobThreads[j].Id = j; } } StartEnvir(); string canstartserver = CanStartEnvir(); if (canstartserver != "true") { SMain.Enqueue(canstartserver); StopEnvir(); _thread = null; Stop(); return; } if (Settings.Multithreaded) { for (int j = 0; j < MobThreads.Length; j++) { MobThread Info = MobThreads[j]; if (j > 0) //dont start up 0 { MobThreading[j] = new Thread(() => ThreadLoop(Info)); MobThreading[j].IsBackground = true; MobThreading[j].Start(); } } } StartNetwork(); try { while (Running) { Time = Stopwatch.ElapsedMilliseconds; if (Time >= processTime) { LastCount = processCount; LastRealCount = processRealCount; processCount = 0; processRealCount = 0; processTime = Time + 1000; } if (conTime != Time) { conTime = Time; AdjustLights(); lock (Connections) { for (int i = Connections.Count - 1; i >= 0; i--) { Connections[i].Process(); } } lock (StatusConnections) { for (int i = StatusConnections.Count - 1; i >= 0; i--) { StatusConnections[i].Process(); } } } if (current == null) current = Objects.First; if (current == Objects.First) { LastRunTime = Time - StartTime; StartTime = Time; } if (Settings.Multithreaded) { for (int j = 1; j < MobThreads.Length; j++) { MobThread Info = MobThreads[j]; if (Info.Stop == true) { Info.EndTime = Time + 20; Info.Stop = false; } } lock (_locker) { Monitor.PulseAll(_locker); // changing a blocking condition. (this makes the threads wake up!) } //run the first loop in the main thread so the main thread automaticaly 'halts' untill the other threads are finished ThreadLoop(MobThreads[0]); } Boolean TheEnd = false; long Start = Stopwatch.ElapsedMilliseconds; while ((!TheEnd) && (Stopwatch.ElapsedMilliseconds - Start < 20)) { if (current == null) { TheEnd = true; break; } else { LinkedListNode<MapObject> next = current.Next; if (!Settings.Multithreaded || ((current.Value.Race != ObjectType.Monster) || (current.Value.Master != null))) { if (Time > current.Value.OperateTime) { current.Value.Process(); current.Value.SetOperateTime(); } processCount++; } current = next; } } for (int i = 0; i < MapList.Count; i++) MapList[i].Process(); if (DragonSystem != null) DragonSystem.Process(); Process(); if (Time >= saveTime) { saveTime = Time + Settings.SaveDelay * Settings.Minute; BeginSaveAccounts(); SaveGuilds(); SaveGoods(); } if (Time >= userTime) { userTime = Time + Settings.Minute * 5; Broadcast(new S.Chat { Message = string.Format("Online Players: {0}", Players.Count), Type = ChatType.Hint }); } // if (Players.Count == 0) Thread.Sleep(1); // GC.Collect(); } } catch (Exception ex) { SMain.Enqueue(ex); lock (Connections) { for (int i = Connections.Count - 1; i >= 0; i--) Connections[i].SendDisconnect(3); } File.AppendAllText(@".\Error.txt", string.Format("[{0}] {1}{2}", Now, ex, Environment.NewLine)); } StopNetwork(); StopEnvir(); SaveAccounts(); SaveGuilds(true); } catch (Exception ex) { SMain.Enqueue("[outer workloop error]" + ex); File.AppendAllText(@".\Error.txt", string.Format("[{0}] {1}{2}", Now, ex, Environment.NewLine)); } _thread = null; }
private void ThreadLoop(MobThread Info) { Info.Stop = false; long starttime = Time; try { bool stopping = false; if (Info.current == null) Info.current = Info.ObjectsList.First; stopping = Info.current == null; //while (stopping == false) while (Running) { if (Info.current == null) Info.current = Info.ObjectsList.First; else { LinkedListNode<MapObject> next = Info.current.Next; //if we reach the end of our list > go back to the top (since we are running threaded, we dont want the system to sit there for xxms doing nothing) if (Info.current == Info.ObjectsList.Last) { next = Info.ObjectsList.First; Info.LastRunTime = (Info.LastRunTime + (Time - Info.StartTime)) / 2; //Info.LastRunTime = (Time - Info.StartTime) /*> 0 ? (Time - Info.StartTime) : Info.LastRunTime */; Info.StartTime = Time; } if (Time > Info.current.Value.OperateTime) { if (Info.current.Value.Master == null)//since we are running multithreaded, dont allow pets to be processed (unless you constantly move pets into their map appropriate thead) { Info.current.Value.Process(); Info.current.Value.SetOperateTime(); } } Info.current = next; } //if it's the main thread > make it loop till the subthreads are done, else make it stop after 'endtime' if (Info.Id == 0) { stopping = true; for (int x = 1; x < MobThreads.Length; x++) if (MobThreads[x].Stop == false) stopping = false; if (stopping) { Info.Stop = stopping; return; } } else { if ((Stopwatch.ElapsedMilliseconds > Info.EndTime) && Running) { Info.Stop = true; lock (_locker) { while (Info.Stop) Monitor.Wait(_locker); } } } } } catch (Exception ex) { if (ex is ThreadInterruptedException) return; SMain.Enqueue(ex); File.AppendAllText(@".\Error.txt", string.Format("[{0}] {1}{2}", Now, ex, Environment.NewLine)); } //Info.Stop = true; }