diff --git a/Scripts/Mobiles/AI/BaseAI.cs b/Scripts/Mobiles/AI/BaseAI.cs index 31f00081e..1defc9343 100644 --- a/Scripts/Mobiles/AI/BaseAI.cs +++ b/Scripts/Mobiles/AI/BaseAI.cs @@ -2,6 +2,10 @@ using System; using System.Collections; using System.Collections.Generic; using System.IO; +#if Framework_4_0 +using System.Linq; +using System.Threading.Tasks; +#endif using Server; using Server.Items; using Server.Targeting; @@ -2490,6 +2494,7 @@ namespace Server.Mobiles IPooledEnumerable eable = map.GetMobilesInRange(m_Mobile.Location, iRange); +#if !Framework_4_0 foreach (Mobile m in eable) { if (m.Deleted || m.Blessed) @@ -2582,6 +2587,105 @@ namespace Server.Mobiles val = theirVal; } } +#endif + +#if Framework_4_0 + object valLock = new object(); + + Parallel.ForEach( eable.Cast(), m => { + if (m.Deleted || m.Blessed) + return; + + // Let's not target ourselves... + if (m == m_Mobile || m is BaseFamiliar) + return; + + // Dead targets are invalid. + if (!m.Alive || m.IsDeadBondedPet) + return; + + // Staff members cannot be targeted. + if (m.AccessLevel > AccessLevel.Player) + return; + + // Does it have to be a player? + if (bPlayerOnly && !m.Player) + return; + + // Can't acquire a target we can't see. + if (!m_Mobile.CanSee(m)) + return; + + if (Core.AOS && m is BaseCreature && (m as BaseCreature).Summoned && !(m as BaseCreature).Controlled) + return; + + if (m_Mobile.Summoned && m_Mobile.SummonMaster != null) + { + // If this is a summon, it can't target its controller. + if (m == m_Mobile.SummonMaster) + return; + + // It also must abide by harmful spell rules. + if (!Server.Spells.SpellHelper.ValidIndirectTarget(m_Mobile.SummonMaster, m)) + return; + + // Animated creatures cannot attack players directly. + if (m is PlayerMobile && m_Mobile.IsAnimatedDead) + return; + } + + // If we only want faction friends, make sure it's one. + if (bFacFriend && !m_Mobile.IsFriend(m)) + return; + + //Ignore anyone under EtherealVoyage + if (TransformationSpellHelper.UnderTransformation(m, typeof(EtherealVoyageSpell))) + return; + + // Ignore players with activated honor + if (m is PlayerMobile && ((PlayerMobile)m).HonorActive && !(m_Mobile.Combatant == m)) + return; + + if (acqType == FightMode.Aggressor || acqType == FightMode.Evil) + { + bool bValid = IsHostile(m); + + if (!bValid) + bValid = (m_Mobile.GetFactionAllegiance(m) == BaseCreature.Allegiance.Enemy || m_Mobile.GetEthicAllegiance(m) == BaseCreature.Allegiance.Enemy); + + if (acqType == FightMode.Evil && !bValid) + { + if (m is BaseCreature && ((BaseCreature)m).Controlled && ((BaseCreature)m).ControlMaster != null) + bValid = (((BaseCreature)m).ControlMaster.Karma < 0); + else + bValid = (m.Karma < 0); + } + + if (!bValid) + return; + } + else + { + // Same goes for faction enemies. + if (bFacFoe && !m_Mobile.IsEnemy(m)) + return; + + // If it's an enemy factioned mobile, make sure we can be harmful to it. + if (bFacFoe && !bFacFriend && !m_Mobile.CanBeHarmful(m, false)) + return; + } + + theirVal = m_Mobile.GetFightModeRanking(m, acqType, bPlayerOnly); + + lock (valLock) { + if (theirVal > val && m_Mobile.InLOS(m)) + { + newFocusMob = m; + val = theirVal; + } + } + }); +#endif eable.Free(); diff --git a/Scripts/Mobiles/BaseCreature.cs b/Scripts/Mobiles/BaseCreature.cs index d03c62c63..ad89fc8eb 100644 --- a/Scripts/Mobiles/BaseCreature.cs +++ b/Scripts/Mobiles/BaseCreature.cs @@ -5645,7 +5645,7 @@ namespace Server.Mobiles return base.CanBeDamaged(); } - public virtual bool PlayerRangeSensitive{ get{ return (this.CurrentWayPoint == null); } } //If they are following a waypoint, they'll continue to follow it even if players aren't around + public virtual bool PlayerRangeSensitive{ get{ return (this.CurrentWayPoint != null); } } //If they are following a waypoint, they'll continue to follow it even if players aren't around /* until we are sure about who should be getting deleted, move them instead */ /* On OSI, they despawn */ diff --git a/Server/Map.cs b/Server/Map.cs index 2c0dc0277..f02e8543f 100644 --- a/Server/Map.cs +++ b/Server/Map.cs @@ -1098,9 +1098,24 @@ namespace Server { private IPooledEnumerator m_Enumerator; + private static Queue m_InstancePool = new Queue(); + public static PooledEnumerable Instantiate( IPooledEnumerator etor ) { - PooledEnumerable e = new PooledEnumerable( etor ); + PooledEnumerable e = null; + + lock (m_InstancePool) { + if ( m_InstancePool.Count > 0 ) { + e = m_InstancePool.Dequeue(); + e.m_Enumerator = etor; + } + } + + if (e == null ) + e = new PooledEnumerable( etor ); + + etor.Enumerable = e; + return e; } @@ -1112,18 +1127,20 @@ namespace Server public IEnumerator GetEnumerator() { if ( m_Enumerator == null ) - throw new ObjectDisposedException("PooledEnumerable", "GetEnumerator() called after Free()"); + throw new ObjectDisposedException( "PooledEnumerable", "GetEnumerator() called after Free()" ); return m_Enumerator; } public void Free() { - if ( m_Enumerator != null ) - { - m_Enumerator.Free(); - m_Enumerator = null; + if ( m_Enumerator != null ) { + m_Enumerator.Free(); + m_Enumerator = null; } + + lock (m_InstancePool) + m_InstancePool.Enqueue( this ); } public void Dispose() @@ -1141,7 +1158,7 @@ namespace Server Clients } - private class TypedEnumerator : IPooledEnumerator, IDisposable + private class TypedEnumerator : IPooledEnumerator { private IPooledEnumerable m_Enumerable; @@ -1157,10 +1174,28 @@ namespace Server private SectorEnumeratorType m_Type; private object m_Current; - public static TypedEnumerator Instantiate( Map map, Rectangle2D bounds, SectorEnumeratorType type ) { - TypedEnumerator e = new TypedEnumerator(map, bounds, type); + private static Queue m_InstancePool = new Queue(); + + public static TypedEnumerator Instantiate( Map map, Rectangle2D bounds, SectorEnumeratorType type ) + { + TypedEnumerator e = null; + + lock (m_InstancePool) { + if ( m_InstancePool.Count > 0 ) { + e = m_InstancePool.Dequeue(); + + e.m_Map = map; + e.m_Bounds = bounds; + e.m_Type = type; + } + } + + if (e == null) { + e = new TypedEnumerator( map, bounds, type ); + } e.Reset(); + return e; } @@ -1169,13 +1204,15 @@ namespace Server if ( m_Map == null ) return; - if ( m_Enumerator != null ) - { + m_Map = null; + + if ( m_Enumerator != null) { m_Enumerator.Free(); m_Enumerator = null; } - m_Map = null; + lock (m_InstancePool) + m_InstancePool.Enqueue( this ); } public TypedEnumerator( Map map, Rectangle2D bounds, SectorEnumeratorType type ) @@ -1185,86 +1222,55 @@ namespace Server m_Type = type; } - public object Current { - get { return m_Current; } - } + public object Current { get { return m_Current; } } public bool MoveNext() { - while ( true ) - { - if (m_Enumerator == null) - { - Console.WriteLine("hmm m_Enumerator null??"); - return false; + while ( m_Enumerator.MoveNext() ) { + object o; + + try { + o = m_Enumerator.Current; + } catch { + continue; } - if ( m_Enumerator.MoveNext() ) - { - object o; + if ( o is Mobile ) { + Mobile m = (Mobile) o; - try - { - o = m_Enumerator.Current; - } - catch - { - Console.WriteLine("typed Enum current null"); - continue; + if ( !m.Deleted && m_Bounds.Contains( m.Location ) ) { + m_Current = o; + return true; } + } else if ( o is Item ) { + Item item = (Item) o; - if ( o is Mobile ) - { - Mobile m = (Mobile) o; - - if ( !m.Deleted && m_Bounds.Contains( m.Location ) ) - { - m_Current = o; - return true; - } + if ( !item.Deleted && item.Parent == null && m_Bounds.Contains( item.Location ) ) { + m_Current = o; + return true; } - else if ( o is Item ) - { - Item item = (Item) o; + } else if ( o is NetState ) { + Mobile m = ( (NetState) o ).Mobile; - if ( !item.Deleted && item.Parent == null && m_Bounds.Contains( item.Location ) ) - { - m_Current = o; - return true; - } + if ( m != null && !m.Deleted && m_Bounds.Contains( m.Location ) ) { + m_Current = o; + return true; } - else if ( o is NetState ) - { - Mobile m = ( (NetState) o ).Mobile; - - if ( m != null && !m.Deleted && m_Bounds.Contains( m.Location ) ) - { - m_Current = o; - return true; - } - } - } - else - { - m_Current = null; - return false; } } + + m_Current = null; + return false; } public void Reset() { m_Current = null; - m_Enumerator = SectorEnumerator.Instantiate( m_Map, m_Bounds, m_Type ); - } - - public void Dispose() - { - Free(); + m_Enumerator = SectorEnumerator.Instantiate( m_Map, m_Bounds, m_Type );//new SectorEnumerator( m_Map, m_Origin, m_Type, m_Range ); } } - private class MultiTileEnumerator : IPooledEnumerator, IDisposable + private class MultiTileEnumerator : IPooledEnumerator { private IPooledEnumerable m_Enumerable; @@ -1279,11 +1285,27 @@ namespace Server private object m_Current; private int m_Index; + private static Queue m_InstancePool = new Queue(); + public static MultiTileEnumerator Instantiate( Sector sector, Point2D loc ) { - MultiTileEnumerator e = new MultiTileEnumerator( sector, loc ); + MultiTileEnumerator e = null; + + lock (m_InstancePool) { + if ( m_InstancePool.Count > 0 ) { + e = m_InstancePool.Dequeue(); + + e.m_List = sector.Multis; + e.m_Location = loc; + } + } + + if (e == null) { + e = new MultiTileEnumerator( sector, loc ); + } e.Reset(); + return e; } @@ -1293,11 +1315,7 @@ namespace Server m_Location = loc; } - public object Current { - get { - return m_Current; - } - } + public object Current { get { return m_Current; } } public bool MoveNext() { @@ -1342,7 +1360,10 @@ namespace Server if ( m_List == null ) return; - m_List = null; + lock (m_InstancePool) { + m_InstancePool.Enqueue( this ); + m_List = null; + } } public void Reset() @@ -1350,14 +1371,9 @@ namespace Server m_Current = null; m_Index = -1; } - - public void Dispose() - { - Free(); - } } - private class ObjectEnumerator : IPooledEnumerator, IDisposable + private class ObjectEnumerator : IPooledEnumerator { private IPooledEnumerable m_Enumerable; @@ -1373,11 +1389,27 @@ namespace Server private int m_Stage; // 0 = items, 1 = mobiles private object m_Current; + private static Queue m_InstancePool = new Queue(); + public static ObjectEnumerator Instantiate( Map map, Rectangle2D bounds ) { - ObjectEnumerator e = new ObjectEnumerator(map, bounds); + ObjectEnumerator e = null; + + lock (m_InstancePool) { + if ( m_InstancePool.Count > 0 ) { + e = m_InstancePool.Dequeue(); + + e.m_Map = map; + e.m_Bounds = bounds; + } + } + + if (e == null) { + e = new ObjectEnumerator( map, bounds ); + } e.Reset(); + return e; } @@ -1388,11 +1420,13 @@ namespace Server m_Map = null; - if ( m_Enumerator != null ) - { + if ( m_Enumerator != null ) { m_Enumerator.Free(); m_Enumerator = null; } + + lock (m_InstancePool) + m_InstancePool.Enqueue( this ); } private ObjectEnumerator( Map map, Rectangle2D bounds ) @@ -1417,7 +1451,6 @@ namespace Server } catch { - Console.WriteLine("OBJ Enum current null"); continue; } @@ -1474,14 +1507,9 @@ namespace Server m_Enumerator = SectorEnumerator.Instantiate( m_Map, m_Bounds, SectorEnumeratorType.Items ); } - - public void Dispose() - { - Free(); - } } - private class SectorEnumerator : IPooledEnumerator, IDisposable + private class SectorEnumerator : IPooledEnumerator { private IPooledEnumerable m_Enumerable; @@ -1503,10 +1531,26 @@ namespace Server private static Queue m_InstancePool = new Queue(); - public static SectorEnumerator Instantiate( Map map, Rectangle2D bounds, SectorEnumeratorType type ) { - SectorEnumerator e = new SectorEnumerator(map, bounds, type); + public static SectorEnumerator Instantiate( Map map, Rectangle2D bounds, SectorEnumeratorType type ) + { + SectorEnumerator e = null; + + lock (m_InstancePool) { + if ( m_InstancePool.Count > 0 ) { + e = m_InstancePool.Dequeue(); + + e.m_Map = map; + e.m_Bounds = bounds; + e.m_Type = type; + } + } + + if (e == null) { + e = new SectorEnumerator( map, bounds, type ); + } e.Reset(); + return e; } @@ -1515,7 +1559,13 @@ namespace Server if ( m_Map == null ) return; - //m_Map = null; + m_Map = null; + + if ( m_Enumerable != null ) + m_Enumerable.Free(); + + lock (m_InstancePool) + m_InstancePool.Enqueue( this ); } private SectorEnumerator( Map map, Rectangle2D bounds, SectorEnumeratorType type ) @@ -1540,8 +1590,32 @@ namespace Server } } - public object Current { - get { return m_CurrentList[m_CurrentIndex]; } + public object Current + { + get + { + return m_CurrentList[m_CurrentIndex]; + /*try + { + return m_CurrentList[m_CurrentIndex]; + } + catch + { + Console.WriteLine( "Warning: Object removed during enumeration. May not be recoverable" ); + + m_CurrentIndex = -1; + m_CurrentList = GetListForSector( m_Map.InternalGetSector( m_xSector, m_ySector ) ); + + if ( MoveNext() ) + { + return Current; + } + else + { + throw new Exception( "Object disposed during enumeration. Was not recoverable." ); + } + }*/ + } } public bool MoveNext() @@ -1550,9 +1624,6 @@ namespace Server { ++m_CurrentIndex; - if (m_CurrentList == null) - return false; // So much fail with PooledEnumerables >< - if ( m_CurrentIndex == m_CurrentList.Count ) { ++m_ySector; @@ -1565,8 +1636,6 @@ namespace Server if ( m_xSector > m_xSectorEnd ) { m_CurrentIndex = -1; - m_CurrentList = null; - return false; } } @@ -1595,11 +1664,6 @@ namespace Server m_CurrentIndex = -1; m_CurrentList = GetListForSector( m_Map.InternalGetSector( m_xSector, m_ySector ) ); } - - public void Dispose() - { - Free(); - } } #endregion diff --git a/Server/Mobile.cs b/Server/Mobile.cs index b7c45659e..00a6d9a43 100644 --- a/Server/Mobile.cs +++ b/Server/Mobile.cs @@ -4016,29 +4016,31 @@ namespace Server if( m_Map != null ) { - Packet animPacket = null;//new DeathAnimation( this, c ); - Packet remPacket = null;//this.RemovePacket; + Packet animPacket = null; + object pLock = new object(); IPooledEnumerable eable = m_Map.GetClientsInRange( m_Location ); - foreach( NetState state in eable ) - { - if( state != m_NetState ) - { - if( animPacket == null ) - animPacket = Packet.Acquire( new DeathAnimation( this, c ) ); +#if Framework_4_0 + Parallel.ForEach( eable.Cast(), state => { +#else + foreach( NetState state in eable ) { +#endif + if( state != m_NetState ) { + lock (pLock) + if (animPacket == null) + animPacket = Packet.Acquire( new DeathAnimation( this, c ) );; state.Send( animPacket ); - if( !state.Mobile.CanSee( this ) ) - { - if( remPacket == null ) - remPacket = this.RemovePacket; - - state.Send( remPacket ); + if( !state.Mobile.CanSee( this ) ) { + state.Send( this.RemovePacket ); } } } +#if Framework_4_0 + ); +#endif Packet.Release( animPacket ); @@ -5363,31 +5365,33 @@ namespace Server Packet pNew = null; Packet pOld = null; + object pLock1 = new object(); + object pLock2 = new object(); - foreach( NetState ns in eable ) - { - if( ns.Mobile.CanSee( this ) ) - { - Packet p; +#if Framework_4_0 + Parallel.ForEach( eable.Cast(), ns => { +#else + foreach( NetState ns in eable ) { +#endif + if( ns.Mobile.CanSee( this ) ) { + if( ns.DamagePacket ) { + lock (pLock1) + if( pNew == null ) + pNew = Packet.Acquire( new DamagePacket( this, amount ) ); - if( ns.DamagePacket ) - { - if( pNew == null ) - pNew = Packet.Acquire( new DamagePacket( this, amount ) ); + ns.Send( pNew ); + } else { + lock (pLock2) + if( pOld == null ) + pOld = Packet.Acquire( new DamagePacketOld( this, amount ) ); - p = pNew; + ns.Send( pOld ); } - else - { - if( pOld == null ) - pOld = Packet.Acquire( new DamagePacketOld( this, amount ) ); - - p = pOld; - } - - ns.Send( p ); } } +#if Framework_4_0 + ); +#endif Packet.Release( pNew ); Packet.Release( pOld ); @@ -6360,20 +6364,22 @@ namespace Server if( m_Map != null ) { - Packet p = null; + Packet p = Packet.Acquire(new PlaySound(soundID, this)); IPooledEnumerable eable = m_Map.GetClientsInRange( m_Location ); - foreach( NetState state in eable ) - { - if( state.Mobile.CanSee( this ) ) - { - if( p == null ) - p = Packet.Acquire( new PlaySound( soundID, this ) ); - +#if Framework_4_0 + Parallel.ForEach( eable.Cast(), state => { +#else + foreach( NetState state in eable ) { +#endif + if( state.Mobile.CanSee( this ) ) { state.Send( p ); } } +#if Framework_4_0 + ); +#endif Packet.Release( p ); @@ -6631,20 +6637,19 @@ namespace Server { if( m_Map != null ) { - Packet p = null; - IPooledEnumerable eable = m_Map.GetClientsInRange( m_Location ); - foreach( NetState state in eable ) - { +#if Framework_4_0 + Parallel.ForEach( eable.Cast(), state => { +#else + foreach( NetState state in eable ) { +#endif if( state != m_NetState && (everyone || !state.Mobile.CanSee( this )) ) - { - if( p == null ) - p = this.RemovePacket; - - state.Send( p ); - } + state.Send( this.RemovePacket ); } +#if Framework_4_0 + ); +#endif eable.Free(); } @@ -10655,25 +10660,27 @@ namespace Server { Packet p = null; + if( ascii ) + p = new AsciiMessage( m_Serial, Body, type, hue, 3, Name, text ); + else + p = new UnicodeMessage( m_Serial, Body, type, hue, 3, m_Language, Name, text ); + + p.Acquire(); + IPooledEnumerable eable = m_Map.GetClientsInRange( m_Location ); - foreach( NetState state in eable ) - { - if( state.Mobile.CanSee( this ) && (noLineOfSight || state.Mobile.InLOS( this )) ) - { - if( p == null ) - { - if( ascii ) - p = new AsciiMessage( m_Serial, Body, type, hue, 3, Name, text ); - else - p = new UnicodeMessage( m_Serial, Body, type, hue, 3, m_Language, Name, text ); - - p.Acquire(); - } - +#if Framework_4_0 + Parallel.ForEach( eable.Cast(), state => { +#else + foreach( NetState state in eable ) { +#endif + if( state.Mobile.CanSee( this ) && (noLineOfSight || state.Mobile.InLOS( this )) ) { state.Send( p ); } } +#if Framework_4_0 + ); +#endif Packet.Release( p ); @@ -10695,20 +10702,22 @@ namespace Server { if( m_Map != null ) { - Packet p = null; + Packet p = Packet.Acquire( new MessageLocalized( m_Serial, Body, type, hue, 3, number, Name, args ) ); IPooledEnumerable eable = m_Map.GetClientsInRange( m_Location ); - foreach( NetState state in eable ) - { - if( state.Mobile.CanSee( this ) && (noLineOfSight || state.Mobile.InLOS( this )) ) - { - if( p == null ) - p = Packet.Acquire( new MessageLocalized( m_Serial, Body, type, hue, 3, number, Name, args ) ); - +#if Framework_4_0 + Parallel.ForEach( eable.Cast(), state => { +#else + foreach( NetState state in eable ) { +#endif + if( state.Mobile.CanSee( this ) && (noLineOfSight || state.Mobile.InLOS( this )) ) { state.Send( p ); } } +#if Framework_4_0 + ); +#endif Packet.Release( p ); @@ -10725,20 +10734,22 @@ namespace Server { if( m_Map != null ) { - Packet p = null; + Packet p = Packet.Acquire( new MessageLocalizedAffix( m_Serial, Body, type, hue, 3, number, Name, affixType, affix, args ) ); IPooledEnumerable eable = m_Map.GetClientsInRange( m_Location ); - foreach( NetState state in eable ) - { - if( state.Mobile.CanSee( this ) && (noLineOfSight || state.Mobile.InLOS( this )) ) - { - if( p == null ) - p = Packet.Acquire( new MessageLocalizedAffix( m_Serial, Body, type, hue, 3, number, Name, affixType, affix, args ) ); - +#if Framework_4_0 + Parallel.ForEach( eable.Cast(), state => { +#else + foreach( NetState state in eable ) { +#endif + if( state.Mobile.CanSee( this ) && (noLineOfSight || state.Mobile.InLOS( this )) ) { state.Send( p ); } } +#if Framework_4_0 + ); +#endif Packet.Release( p ); @@ -10805,20 +10816,22 @@ namespace Server { if( m_Map != null ) { - Packet p = null; + Packet p = Packet.Acquire( new MessageLocalized( m_Serial, Body, type, hue, 3, number, Name, args ) ); IPooledEnumerable eable = m_Map.GetClientsInRange( m_Location ); - foreach( NetState state in eable ) - { - if( state != m_NetState && state.Mobile.CanSee( this ) ) - { - if( p == null ) - p = Packet.Acquire( new MessageLocalized( m_Serial, Body, type, hue, 3, number, Name, args ) ); - +#if Framework_4_0 + Parallel.ForEach( eable.Cast(), state => { +#else + foreach( NetState state in eable ) { +#endif + if( state != m_NetState && state.Mobile.CanSee( this ) ) { state.Send( p ); } } +#if Framework_4_0 + ); +#endif Packet.Release( p ); @@ -10832,25 +10845,27 @@ namespace Server { Packet p = null; + if( ascii ) + p = new AsciiMessage( m_Serial, Body, type, hue, 3, Name, text ); + else + p = new UnicodeMessage( m_Serial, Body, type, hue, 3, Language, Name, text ); + + p.Acquire(); + IPooledEnumerable eable = m_Map.GetClientsInRange( m_Location ); - foreach( NetState state in eable ) - { - if( state != m_NetState && state.Mobile.CanSee( this ) ) - { - if( p == null ) - { - if( ascii ) - p = new AsciiMessage( m_Serial, Body, type, hue, 3, Name, text ); - else - p = new UnicodeMessage( m_Serial, Body, type, hue, 3, Language, Name, text ); - - p.Acquire(); - } - +#if Framework_4_0 + Parallel.ForEach( eable.Cast(), state => { +#else + foreach( NetState state in eable ) { +#endif + if( state != m_NetState && state.Mobile.CanSee( this ) ) { state.Send( p ); } } +#if Framework_4_0 + ); +#endif Packet.Release( p ); diff --git a/Server/Network/NetState.cs b/Server/Network/NetState.cs index 9eabb4f3a..a33d43ffa 100644 --- a/Server/Network/NetState.cs +++ b/Server/Network/NetState.cs @@ -1125,8 +1125,10 @@ namespace Server.Network { TraceException( ex ); } - if ( m_RecvBuffer != null ) - m_ReceiveBufferPool.ReleaseBuffer( m_RecvBuffer ); + if ( m_RecvBuffer != null ) { + lock (m_ReceiveBufferPool) + m_ReceiveBufferPool.ReleaseBuffer( m_RecvBuffer ); + } m_Socket = null; @@ -1158,9 +1160,13 @@ namespace Server.Network { public static void CheckAllAlive() { try { +#if Framework_4_0 + Parallel.ForEach( m_Instances, ns => ns.CheckAlive() ); +#else for ( int i = 0; i < m_Instances.Count; ++i ) { m_Instances[i].CheckAlive(); } +#endif } catch ( Exception ex ) { TraceException( ex ); }