Level Extreme platform
Subscription
Corporate profile
Products & Services
Support
Legal
Français
Conversion from C# to VB.NET
Message
From
19/04/2013 08:01:57
 
 
General information
Forum:
ASP.NET
Category:
Coding, syntax and commands
Environment versions
Environment:
VB 9.0
OS:
Windows 7
Network:
Windows 2003 Server
Database:
MS SQL Server
Application:
Web
Miscellaneous
Thread ID:
01571173
Message ID:
01571462
Views:
47
>>>Still don't see it. Given this:
       public string[] Tables = new string[] { "One", "Two", "Three" };
>>>     
>>>
>>>        public void UseTables()
>>>        {
>>>            foreach (string s in Tables)
>>>            {
>>>                //Do something
>>>                System.Threading.Thread.Sleep(1000);
>>>            }
>>>        }
>>>
>>>        public void LoadDataDictionary()
>>>        {
>>>            string[] tables = new string[]{"One","Two"};
>>>            Tables = tables;
>>>        }
>>>
If, for example, LoadDataDictionary() runs on one thread whilst UseTables() is running on another you've got problems...
>>
>>
>>My first thought was - this has to work.
>>
>>So, I have tested this on the same thread
>>
>>A foreach is nothing but an enumerator. So, I tested with (a) an enumerator and (b) with a foreach loop
>>In the middle of the loop , I assign a new Table - mind you, I do not change the contents of Tables - just replace it with a new occurrence
>>
>>And what I expected is true - it works and continues with the 'old' Tables
>>
>>The reason it continues to work is that the foreach, when it starts, stores a reference to Tables in a local variable and continues to work with the local variable
>>During the first iteration, Tables is replaced with a new array, but the loop continues to work with the reference it saved at the beginning of the loop
>>The old object Tables continues to be referenced during the life time of the loop and during that time will not be garbage collected
>>
>>IldAsm listing of foreach at the end
>>
>>
>>	public class AClass
>>	{
>>		public static string[] Tables;
>>
>>		public static void Main()
>>		{
>>			TestWithEnumerator();
>>			TestWithForEach();
>>		}
>>
>>		static void TestWithEnumerator()
>>		{
>>			InitializeTables();
>>			var enumerator = Tables.GetEnumerator();
>>			while (enumerator.MoveNext())
>>			{
>>				Console.WriteLine(enumerator.Current);
>>				ReInitializeTables();
>>			}
>>			Console.ReadLine();
>>		}
>>		static void TestWithForEach()
>>		{
>>			InitializeTables();
>>			foreach (var x in Tables )
>>			{
>>				Console.WriteLine(x);
>>				ReInitializeTables();
>>			}
>>			Console.ReadLine();
>>		}
>>
>>		public static void InitializeTables()
>>		{
>>			string[] tables = new string[] { "one", "two", "three" };
>>			Tables = tables;
>>		}
>>
>>		public static void ReInitializeTables()
>>		{
>>			string[] tables = new string[] { "four", "five" };
>>			Tables = tables;
>>		}
>>	}
>>
>>
>>ild
>>
>>.method private hidebysig static void  TestWithForEach() cil managed
>>{
>>  // Code size       58 (0x3a)
>>  .maxstack  2
>>  .locals init ([0] string x,
>>           [1] string[] CS$6$0000,
>>           [2] int32 CS$7$0001,
>>           [3] bool CS$4$0002)
>>  IL_0000:  nop
>>  IL_0001:  call       void CoreTest.AClass::InitializeTables()
>>  IL_0006:  nop
>>  IL_0007:  nop
>>  IL_0008:  ldsfld     string[] CoreTest.AClass::Tables                     loads static field Tables on the stack
>>  IL_000d:  stloc.1                                                                                   and stores it locally
>>  IL_000e:  ldc.i4.0
>>  IL_000f:  stloc.2
>>  IL_0010:  br.s       IL_0029
>>  IL_0012:  ldloc.1
>>  IL_0013:  ldloc.2
>>  IL_0014:  ldelem.ref
>>  IL_0015:  stloc.0
>>  IL_0016:  nop
>>  IL_0017:  ldloc.0
>>  IL_0018:  call       void [mscorlib]System.Console::WriteLine(string)
>>  IL_001d:  nop
>>  IL_001e:  call       void CoreTest.AClass::ReInitializeTables()
>>  IL_0023:  nop
>>  IL_0024:  nop
>>  IL_0025:  ldloc.2
>>  IL_0026:  ldc.i4.1
>>  IL_0027:  add
>>  IL_0028:  stloc.2
>>  IL_0029:  ldloc.2
>>  IL_002a:  ldloc.1
>>  IL_002b:  ldlen
>>  IL_002c:  conv.i4
>>  IL_002d:  clt
>>  IL_002f:  stloc.3
>>  IL_0030:  ldloc.3
>>  IL_0031:  brtrue.s   IL_0012
>>  IL_0033:  call       string [mscorlib]System.Console::ReadLine()
>>  IL_0038:  pop
>>  IL_0039:  ret
>>} // end of method AClass::TestWithForEach
>>
Interesting. It's cleverer than I thought. But :
        static void TestWithForEach()
>        {
>             int l = Tables.Length;
>            ReInitializeTables();
>            Console.WriteLine(Tables[l]);
>
>            Console.ReadLine();
>        }
Would fail - even without ReInitializeTables()


Bear in mind that Michel stores a refernce of App.oApp.Tables in another object oProcess and continues working with that reference. When App.oApp.Tables is replaced by a new occurrence - oProcess continues to use the previous object
Gregory
Previous
Next
Reply
Map
View

Click here to load this message in the networking platform