diff --git a/snippets/csharp/System.Text.RegularExpressions/Regex/Match/Project.csproj b/snippets/csharp/System.Text/Encoding/Overview/Project.csproj
similarity index 64%
rename from snippets/csharp/System.Text.RegularExpressions/Regex/Match/Project.csproj
rename to snippets/csharp/System.Text/Encoding/Overview/Project.csproj
index 0735dba1f6d..874c98f3477 100644
--- a/snippets/csharp/System.Text.RegularExpressions/Regex/Match/Project.csproj
+++ b/snippets/csharp/System.Text/Encoding/Overview/Project.csproj
@@ -2,7 +2,7 @@
Library
- net6.0
+ net10.0
-
-
+
+
diff --git a/snippets/csharp/System.Text/Encoding/Overview/convert.cs b/snippets/csharp/System.Text/Encoding/Overview/convert.cs
index 8fa227775b0..59060114673 100644
--- a/snippets/csharp/System.Text/Encoding/Overview/convert.cs
+++ b/snippets/csharp/System.Text/Encoding/Overview/convert.cs
@@ -2,9 +2,9 @@
using System;
using System.Text;
-class Example
+class ConvertExample
{
- static void Main()
+ static void Run()
{
string unicodeString = "This string contains the unicode character Pi (\u03a0)";
@@ -28,6 +28,7 @@ static void Main()
Console.WriteLine("Ascii converted string: {0}", asciiString);
}
}
+
// The example displays the following output:
// Original string: This string contains the unicode character Pi (Π)
// Ascii converted string: This string contains the unicode character Pi (?)
diff --git a/snippets/csharp/System.Text/Encoding/Overview/getencoding1.cs b/snippets/csharp/System.Text/Encoding/Overview/getencoding1.cs
new file mode 100644
index 00000000000..01030c658a4
--- /dev/null
+++ b/snippets/csharp/System.Text/Encoding/Overview/getencoding1.cs
@@ -0,0 +1,91 @@
+//
+using System;
+using System.Text;
+
+public class GetEncodingExample
+{
+ public static void Run()
+ {
+ Encoding enc = Encoding.GetEncoding(1253);
+ Encoding altEnc = Encoding.GetEncoding("windows-1253");
+ Console.WriteLine($"{enc.EncodingName} = Code Page {altEnc.CodePage}: {enc.Equals(altEnc)}");
+ string greekAlphabet = "Α α Β β Γ γ Δ δ Ε ε Ζ ζ Η η " +
+ "Θ θ Ι ι Κ κ Λ λ Μ μ Ν ν Ξ ξ " +
+ "Ο ο Π π Ρ ρ Σ σ ς Τ τ Υ υ " +
+ "Φ φ Χ χ Ψ ψ Ω ω";
+ Console.OutputEncoding = Encoding.UTF8;
+ byte[] bytes = enc.GetBytes(greekAlphabet);
+ Console.WriteLine("{0,-12} {1,20} {2,20:X2}", "Character",
+ "Unicode Code Point", "Code Page 1253");
+ for (int ctr = 0; ctr < bytes.Length; ctr++) {
+ if (greekAlphabet[ctr].Equals(' '))
+ continue;
+
+ Console.WriteLine("{0,-12} {1,20} {2,20:X2}", greekAlphabet[ctr],
+ GetCodePoint(greekAlphabet[ctr]), bytes[ctr]);
+ }
+ }
+
+ private static string GetCodePoint(char ch)
+ {
+ string retVal = "u+";
+ byte[] bytes = Encoding.Unicode.GetBytes(ch.ToString());
+ for (int ctr = bytes.Length - 1; ctr >= 0; ctr--)
+ retVal += bytes[ctr].ToString("X2");
+
+ return retVal;
+ }
+}
+
+// The example displays the following output:
+// Character Unicode Code Point Code Page 1253
+// Α u+0391 C1
+// α u+03B1 E1
+// Β u+0392 C2
+// β u+03B2 E2
+// Γ u+0393 C3
+// γ u+03B3 E3
+// Δ u+0394 C4
+// δ u+03B4 E4
+// Ε u+0395 C5
+// ε u+03B5 E5
+// Ζ u+0396 C6
+// ζ u+03B6 E6
+// Η u+0397 C7
+// η u+03B7 E7
+// Θ u+0398 C8
+// θ u+03B8 E8
+// Ι u+0399 C9
+// ι u+03B9 E9
+// Κ u+039A CA
+// κ u+03BA EA
+// Λ u+039B CB
+// λ u+03BB EB
+// Μ u+039C CC
+// μ u+03BC EC
+// Ν u+039D CD
+// ν u+03BD ED
+// Ξ u+039E CE
+// ξ u+03BE EE
+// Ο u+039F CF
+// ο u+03BF EF
+// Π u+03A0 D0
+// π u+03C0 F0
+// Ρ u+03A1 D1
+// ρ u+03C1 F1
+// Σ u+03A3 D3
+// σ u+03C3 F3
+// ς u+03C2 F2
+// Τ u+03A4 D4
+// τ u+03C4 F4
+// Υ u+03A5 D5
+// υ u+03C5 F5
+// Φ u+03A6 D6
+// φ u+03C6 F6
+// Χ u+03A7 D7
+// χ u+03C7 F7
+// Ψ u+03A8 D8
+// ψ u+03C8 F8
+// Ω u+03A9 D9
+// ω u+03C9 F9
+//
diff --git a/snippets/csharp/System.Text/StringBuilder/Overview/Project.csproj b/snippets/csharp/System.Text/StringBuilder/Overview/Project.csproj
new file mode 100644
index 00000000000..22dd9034898
--- /dev/null
+++ b/snippets/csharp/System.Text/StringBuilder/Overview/Project.csproj
@@ -0,0 +1,9 @@
+
+
+
+ Library
+ net10.0
+ true
+
+
+
diff --git a/snippets/csharp/System.Text/StringBuilder/Overview/call1.cs b/snippets/csharp/System.Text/StringBuilder/Overview/call1.cs
new file mode 100644
index 00000000000..ed96e1ca314
--- /dev/null
+++ b/snippets/csharp/System.Text/StringBuilder/Overview/call1.cs
@@ -0,0 +1,19 @@
+//
+using System;
+using System.Text;
+
+public class Example
+{
+ public static void Main()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.Append("This is the beginning of a sentence, ");
+ sb.Replace("the beginning of ", "");
+ sb.Insert(sb.ToString().IndexOf("a ") + 2, "complete ");
+ sb.Replace(",", ".");
+ Console.WriteLine(sb.ToString());
+ }
+}
+// The example displays the following output:
+// This is a complete sentence.
+//
diff --git a/snippets/csharp/System.Text/StringBuilder/Overview/call2.cs b/snippets/csharp/System.Text/StringBuilder/Overview/call2.cs
new file mode 100644
index 00000000000..9fe17b881df
--- /dev/null
+++ b/snippets/csharp/System.Text/StringBuilder/Overview/call2.cs
@@ -0,0 +1,17 @@
+//
+using System;
+using System.Text;
+
+public class Example2
+{
+ public static void Main()
+ {
+ StringBuilder sb = new StringBuilder("This is the beginning of a sentence, ");
+ sb.Replace("the beginning of ", "").Insert(sb.ToString().IndexOf("a ") + 2,
+ "complete ").Replace(",", ".");
+ Console.WriteLine(sb.ToString());
+ }
+}
+// The example displays the following output:
+// This is a complete sentence.
+//
diff --git a/snippets/csharp/System.Text/StringBuilder/Overview/chars1.cs b/snippets/csharp/System.Text/StringBuilder/Overview/chars1.cs
new file mode 100644
index 00000000000..85b3c3c6645
--- /dev/null
+++ b/snippets/csharp/System.Text/StringBuilder/Overview/chars1.cs
@@ -0,0 +1,46 @@
+//
+using System;
+using System.Globalization;
+using System.Text;
+
+public class Example3
+{
+ public static void Main()
+ {
+ Random rnd = new Random();
+ StringBuilder sb = new StringBuilder();
+
+ // Generate 10 random numbers and store them in a StringBuilder.
+ for (int ctr = 0; ctr <= 9; ctr++)
+ sb.Append(rnd.Next().ToString("N5"));
+
+ Console.WriteLine("The original string:");
+ Console.WriteLine(sb.ToString());
+
+ // Decrease each number by one.
+ for (int ctr = 0; ctr < sb.Length; ctr++)
+ {
+ if (Char.GetUnicodeCategory(sb[ctr]) == UnicodeCategory.DecimalDigitNumber)
+ {
+ int number = (int)Char.GetNumericValue(sb[ctr]);
+ number--;
+ if (number < 0) number = 9;
+
+ sb[ctr] = number.ToString()[0];
+ }
+ }
+ Console.WriteLine("\nThe new string:");
+ Console.WriteLine(sb.ToString());
+ }
+}
+// The example displays the following output:
+// The original string:
+// 1,457,531,530.00000940,522,609.000001,668,113,564.000001,998,992,883.000001,792,660,834.00
+// 000101,203,251.000002,051,183,075.000002,066,000,067.000001,643,701,043.000001,702,382,508
+// .00000
+//
+// The new string:
+// 0,346,420,429.99999839,411,598.999990,557,002,453.999990,887,881,772.999990,681,559,723.99
+// 999090,192,140.999991,940,072,964.999991,955,999,956.999990,532,690,932.999990,691,271,497
+// .99999
+//
diff --git a/snippets/csharp/System.Text/StringBuilder/Overview/default1.cs b/snippets/csharp/System.Text/StringBuilder/Overview/default1.cs
new file mode 100644
index 00000000000..76998f10013
--- /dev/null
+++ b/snippets/csharp/System.Text/StringBuilder/Overview/default1.cs
@@ -0,0 +1,45 @@
+//
+using System;
+using System.Reflection;
+using System.Text;
+
+public class Example4
+{
+ public static void Main()
+ {
+ StringBuilder sb = new StringBuilder();
+ ShowSBInfo(sb);
+ sb.Append("This is a sentence.");
+ ShowSBInfo(sb);
+ for (int ctr = 0; ctr <= 10; ctr++)
+ {
+ sb.Append("This is an additional sentence.");
+ ShowSBInfo(sb);
+ }
+ }
+
+ private static void ShowSBInfo(StringBuilder sb)
+ {
+ foreach (var prop in sb.GetType().GetProperties())
+ {
+ if (prop.GetIndexParameters().Length == 0)
+ Console.Write("{0}: {1:N0} ", prop.Name, prop.GetValue(sb));
+ }
+ Console.WriteLine();
+ }
+}
+// The example displays the following output:
+// Capacity: 16 MaxCapacity: 2,147,483,647 Length: 0
+// Capacity: 32 MaxCapacity: 2,147,483,647 Length: 19
+// Capacity: 64 MaxCapacity: 2,147,483,647 Length: 50
+// Capacity: 128 MaxCapacity: 2,147,483,647 Length: 81
+// Capacity: 128 MaxCapacity: 2,147,483,647 Length: 112
+// Capacity: 256 MaxCapacity: 2,147,483,647 Length: 143
+// Capacity: 256 MaxCapacity: 2,147,483,647 Length: 174
+// Capacity: 256 MaxCapacity: 2,147,483,647 Length: 205
+// Capacity: 256 MaxCapacity: 2,147,483,647 Length: 236
+// Capacity: 512 MaxCapacity: 2,147,483,647 Length: 267
+// Capacity: 512 MaxCapacity: 2,147,483,647 Length: 298
+// Capacity: 512 MaxCapacity: 2,147,483,647 Length: 329
+// Capacity: 512 MaxCapacity: 2,147,483,647 Length: 360
+//
diff --git a/snippets/csharp/System.Text/StringBuilder/Overview/delete1.cs b/snippets/csharp/System.Text/StringBuilder/Overview/delete1.cs
new file mode 100644
index 00000000000..4d12e85f086
--- /dev/null
+++ b/snippets/csharp/System.Text/StringBuilder/Overview/delete1.cs
@@ -0,0 +1,44 @@
+//
+using System;
+using System.Text;
+
+public class Example5
+{
+ public static void Main()
+ {
+ StringBuilder sb = new StringBuilder("A StringBuilder object");
+ ShowSBInfo(sb);
+ // Remove "object" from the text.
+ string textToRemove = "object";
+ int pos = sb.ToString().IndexOf(textToRemove);
+ if (pos >= 0)
+ {
+ sb.Remove(pos, textToRemove.Length);
+ ShowSBInfo(sb);
+ }
+ // Clear the StringBuilder contents.
+ sb.Clear();
+ ShowSBInfo(sb);
+ }
+
+ public static void ShowSBInfo(StringBuilder sb)
+ {
+ Console.WriteLine($"\nValue: {sb.ToString()}");
+ foreach (var prop in sb.GetType().GetProperties())
+ {
+ if (prop.GetIndexParameters().Length == 0)
+ Console.Write("{0}: {1:N0} ", prop.Name, prop.GetValue(sb));
+ }
+ Console.WriteLine();
+ }
+}
+// The example displays the following output:
+// Value: A StringBuilder object
+// Capacity: 22 MaxCapacity: 2,147,483,647 Length: 22
+//
+// Value: A StringBuilder
+// Capacity: 22 MaxCapacity: 2,147,483,647 Length: 16
+//
+// Value:
+// Capacity: 22 MaxCapacity: 2,147,483,647 Length: 0
+//
diff --git a/snippets/csharp/System.Text/StringBuilder/Overview/expand1.cs b/snippets/csharp/System.Text/StringBuilder/Overview/expand1.cs
new file mode 100644
index 00000000000..50353a4619a
--- /dev/null
+++ b/snippets/csharp/System.Text/StringBuilder/Overview/expand1.cs
@@ -0,0 +1,48 @@
+//
+using System;
+using System.Text;
+
+public class Example6
+{
+ public static void Main()
+ {
+ // Create a StringBuilder object with no text.
+ StringBuilder sb = new StringBuilder();
+ // Append some text.
+ sb.Append('*', 10).Append(" Adding Text to a StringBuilder Object ").Append('*', 10);
+ sb.AppendLine("\n");
+ sb.AppendLine("Some code points and their corresponding characters:");
+ // Append some formatted text.
+ for (int ctr = 50; ctr <= 60; ctr++)
+ {
+ sb.AppendFormat("{0,12:X4} {1,12}", ctr, Convert.ToChar(ctr));
+ sb.AppendLine();
+ }
+ // Find the end of the introduction to the column.
+ int pos = sb.ToString().IndexOf("characters:") + 11 +
+ Environment.NewLine.Length;
+ // Insert a column header.
+ sb.Insert(pos, $"{Environment.NewLine}{"Code Unit",12} {"Character",12}{Environment.NewLine}");
+
+ // Convert the StringBuilder to a string and display it.
+ Console.WriteLine(sb.ToString());
+ }
+}
+// The example displays the following output:
+// ********** Adding Text to a StringBuilder Object **********
+//
+// Some code points and their corresponding characters:
+//
+// Code Unit Character
+// 0032 2
+// 0033 3
+// 0034 4
+// 0035 5
+// 0036 6
+// 0037 7
+// 0038 8
+// 0039 9
+// 003A :
+// 003B ;
+// 003C <
+//
diff --git a/snippets/csharp/System.Text/StringBuilder/Overview/immutability2.cs b/snippets/csharp/System.Text/StringBuilder/Overview/immutability2.cs
new file mode 100644
index 00000000000..1bdd80a7212
--- /dev/null
+++ b/snippets/csharp/System.Text/StringBuilder/Overview/immutability2.cs
@@ -0,0 +1,21 @@
+//
+using System;
+
+public class Example7
+{
+ public unsafe static void Main()
+ {
+ string value = "This is the first sentence" + ".";
+ fixed (char* start = value)
+ {
+ value = String.Concat(value, "This is the second sentence. ");
+ fixed (char* current = value)
+ {
+ Console.WriteLine(start == current);
+ }
+ }
+ }
+}
+// The example displays the following output:
+// False
+//
diff --git a/snippets/csharp/System.Text/StringBuilder/Overview/instantiate1.cs b/snippets/csharp/System.Text/StringBuilder/Overview/instantiate1.cs
new file mode 100644
index 00000000000..0d91bfb11e7
--- /dev/null
+++ b/snippets/csharp/System.Text/StringBuilder/Overview/instantiate1.cs
@@ -0,0 +1,48 @@
+//
+using System;
+using System.Text;
+
+public class Example8
+{
+ public static void Main()
+ {
+ string value = "An ordinary string";
+ int index = value.IndexOf("An ") + 3;
+ int capacity = 0xFFFF;
+
+ // Instantiate a StringBuilder from a string.
+ StringBuilder sb1 = new StringBuilder(value);
+ ShowSBInfo(sb1);
+
+ // Instantiate a StringBuilder from string and define a capacity.
+ StringBuilder sb2 = new StringBuilder(value, capacity);
+ ShowSBInfo(sb2);
+
+ // Instantiate a StringBuilder from substring and define a capacity.
+ StringBuilder sb3 = new StringBuilder(value, index,
+ value.Length - index,
+ capacity);
+ ShowSBInfo(sb3);
+ }
+
+ public static void ShowSBInfo(StringBuilder sb)
+ {
+ Console.WriteLine($"\nValue: {sb.ToString()}");
+ foreach (var prop in sb.GetType().GetProperties())
+ {
+ if (prop.GetIndexParameters().Length == 0)
+ Console.Write("{0}: {1:N0} ", prop.Name, prop.GetValue(sb));
+ }
+ Console.WriteLine();
+ }
+}
+// The example displays the following output:
+// Value: An ordinary string
+// Capacity: 18 MaxCapacity: 2,147,483,647 Length: 18
+//
+// Value: An ordinary string
+// Capacity: 65,535 MaxCapacity: 2,147,483,647 Length: 18
+//
+// Value: ordinary string
+// Capacity: 65,535 MaxCapacity: 2,147,483,647 Length: 15
+//
diff --git a/snippets/csharp/System.Text/StringBuilder/Overview/pattern1.cs b/snippets/csharp/System.Text/StringBuilder/Overview/pattern1.cs
new file mode 100644
index 00000000000..afb671908bd
--- /dev/null
+++ b/snippets/csharp/System.Text/StringBuilder/Overview/pattern1.cs
@@ -0,0 +1,66 @@
+//
+using System;
+using System.Text;
+
+public class Example9
+{
+ public static void Main()
+ {
+ Random rnd = new Random();
+ string[] tempF = { "47.6F", "51.3F", "49.5F", "62.3F" };
+ string[] tempC = { "21.2C", "16.1C", "23.5C", "22.9C" };
+ string[][] temps = { tempF, tempC };
+
+ StringBuilder sb = new StringBuilder();
+ var f = new StringBuilderFinder(sb, "F");
+ var baseDate = new DateTime(2013, 5, 1);
+ String[] temperatures = temps[rnd.Next(2)];
+ bool isFahrenheit = false;
+ foreach (var temperature in temperatures)
+ {
+ if (isFahrenheit)
+ sb.AppendFormat("{0:d}: {1}\n", baseDate, temperature);
+ else
+ isFahrenheit = f.SearchAndAppend(String.Format("{0:d}: {1}\n",
+ baseDate, temperature));
+ baseDate = baseDate.AddDays(1);
+ }
+ if (isFahrenheit)
+ {
+ sb.Insert(0, "Average Daily Temperature in Degrees Fahrenheit");
+ sb.Insert(47, "\n\n");
+ }
+ else
+ {
+ sb.Insert(0, "Average Daily Temperature in Degrees Celsius");
+ sb.Insert(44, "\n\n");
+ }
+ Console.WriteLine(sb.ToString());
+ }
+}
+
+public class StringBuilderFinder
+{
+ private StringBuilder sb;
+ private String text;
+
+ public StringBuilderFinder(StringBuilder sb, String textToFind)
+ {
+ this.sb = sb;
+ this.text = textToFind;
+ }
+
+ public bool SearchAndAppend(String stringToSearch)
+ {
+ sb.Append(stringToSearch);
+ return stringToSearch.Contains(text);
+ }
+}
+// The example displays output similar to the following:
+// Average Daily Temperature in Degrees Celsius
+//
+// 5/1/2013: 21.2C
+// 5/2/2013: 16.1C
+// 5/3/2013: 23.5C
+// 5/4/2013: 22.9C
+//
diff --git a/snippets/csharp/System.Text/StringBuilder/Overview/pattern2.cs b/snippets/csharp/System.Text/StringBuilder/Overview/pattern2.cs
new file mode 100644
index 00000000000..baa5e9f78d8
--- /dev/null
+++ b/snippets/csharp/System.Text/StringBuilder/Overview/pattern2.cs
@@ -0,0 +1,45 @@
+//
+using System;
+using System.Text;
+using System.Text.RegularExpressions;
+
+public class Example10
+{
+ public static void Main()
+ {
+ // Create a StringBuilder object with 4 successive occurrences
+ // of each character in the English alphabet.
+ StringBuilder sb = new StringBuilder();
+ for (ushort ctr = (ushort)'a'; ctr <= (ushort)'z'; ctr++)
+ sb.Append(Convert.ToChar(ctr), 4);
+
+ // Create a parallel string object.
+ String sbString = sb.ToString();
+ // Determine where each new character sequence begins.
+ String pattern = @"(\w)\1+";
+ MatchCollection matches = Regex.Matches(sbString, pattern);
+
+ // Uppercase the first occurrence of the sequence, and separate it
+ // from the previous sequence by an underscore character.
+ for (int ctr = matches.Count - 1; ctr >= 0; ctr--)
+ {
+ Match m = matches[ctr];
+ sb[m.Index] = Char.ToUpper(sb[m.Index]);
+ if (m.Index > 0) sb.Insert(m.Index, "_");
+ }
+ // Display the resulting string.
+ sbString = sb.ToString();
+ int line = 0;
+ do
+ {
+ int nChars = line * 80 + 79 <= sbString.Length ?
+ 80 : sbString.Length - line * 80;
+ Console.WriteLine(sbString.Substring(line * 80, nChars));
+ line++;
+ } while (line * 80 < sbString.Length);
+ }
+}
+// The example displays the following output:
+// Aaaa_Bbbb_Cccc_Dddd_Eeee_Ffff_Gggg_Hhhh_Iiii_Jjjj_Kkkk_Llll_Mmmm_Nnnn_Oooo_Pppp_
+// Qqqq_Rrrr_Ssss_Tttt_Uuuu_Vvvv_Wwww_Xxxx_Yyyy_Zzzz
+//
diff --git a/snippets/csharp/System.Text/StringBuilder/Overview/pattern3.cs b/snippets/csharp/System.Text/StringBuilder/Overview/pattern3.cs
new file mode 100644
index 00000000000..4415ba820ca
--- /dev/null
+++ b/snippets/csharp/System.Text/StringBuilder/Overview/pattern3.cs
@@ -0,0 +1,48 @@
+//
+using System;
+using System.Text;
+
+public class Example11
+{
+ public static void Main()
+ {
+ // Create a StringBuilder object with 4 successive occurrences
+ // of each character in the English alphabet.
+ StringBuilder sb = new StringBuilder();
+ for (ushort ctr = (ushort)'a'; ctr <= (ushort)'z'; ctr++)
+ sb.Append(Convert.ToChar(ctr), 4);
+
+ // Iterate the text to determine when a new character sequence occurs.
+ int position = 0;
+ Char current = '\u0000';
+ do
+ {
+ if (sb[position] != current)
+ {
+ current = sb[position];
+ sb[position] = Char.ToUpper(sb[position]);
+ if (position > 0)
+ sb.Insert(position, "_");
+ position += 2;
+ }
+ else
+ {
+ position++;
+ }
+ } while (position <= sb.Length - 1);
+ // Display the resulting string.
+ String sbString = sb.ToString();
+ int line = 0;
+ do
+ {
+ int nChars = line * 80 + 79 <= sbString.Length ?
+ 80 : sbString.Length - line * 80;
+ Console.WriteLine(sbString.Substring(line * 80, nChars));
+ line++;
+ } while (line * 80 < sbString.Length);
+ }
+}
+// The example displays the following output:
+// Aaaa_Bbbb_Cccc_Dddd_Eeee_Ffff_Gggg_Hhhh_Iiii_Jjjj_Kkkk_Llll_Mmmm_Nnnn_Oooo_Pppp_
+// Qqqq_Rrrr_Ssss_Tttt_Uuuu_Vvvv_Wwww_Xxxx_Yyyy_Zzzz
+//
diff --git a/snippets/csharp/System.Text/StringBuilder/Overview/pattern4.cs b/snippets/csharp/System.Text/StringBuilder/Overview/pattern4.cs
new file mode 100644
index 00000000000..c19bb283e94
--- /dev/null
+++ b/snippets/csharp/System.Text/StringBuilder/Overview/pattern4.cs
@@ -0,0 +1,41 @@
+//
+using System;
+using System.Text;
+using System.Text.RegularExpressions;
+
+public class Example12
+{
+ public static void Main()
+ {
+ // Create a StringBuilder object with 4 successive occurrences
+ // of each character in the English alphabet.
+ StringBuilder sb = new StringBuilder();
+ for (ushort ctr = (ushort)'a'; ctr <= (ushort)'z'; ctr++)
+ sb.Append(Convert.ToChar(ctr), 4);
+
+ // Convert it to a string.
+ String sbString = sb.ToString();
+
+ // Use a regex to uppercase the first occurrence of the sequence,
+ // and separate it from the previous sequence by an underscore.
+ string pattern = @"(\w)(\1+)";
+ sbString = Regex.Replace(sbString, pattern,
+ m => (m.Index > 0 ? "_" : "") +
+ m.Groups[1].Value.ToUpper() +
+ m.Groups[2].Value);
+
+ // Display the resulting string.
+ int line = 0;
+ do
+ {
+ int nChars = line * 80 + 79 <= sbString.Length ?
+ 80 : sbString.Length - line * 80;
+ Console.WriteLine(sbString.Substring(line * 80, nChars));
+ line++;
+ } while (line * 80 < sbString.Length);
+ }
+}
+// The example displays the following output:
+// Aaaa_Bbbb_Cccc_Dddd_Eeee_Ffff_Gggg_Hhhh_Iiii_Jjjj_Kkkk_Llll_Mmmm_Nnnn_Oooo_Pppp_
+// Qqqq_Rrrr_Ssss_Tttt_Uuuu_Vvvv_Wwww_Xxxx_Yyyy_Zzzz
+//
diff --git a/snippets/csharp/System.Text/StringBuilder/Overview/replace1.cs b/snippets/csharp/System.Text/StringBuilder/Overview/replace1.cs
new file mode 100644
index 00000000000..10cbf950948
--- /dev/null
+++ b/snippets/csharp/System.Text/StringBuilder/Overview/replace1.cs
@@ -0,0 +1,16 @@
+//
+using System;
+using System.Text;
+
+public class Example13
+{
+ public static void Main()
+ {
+ StringBuilder MyStringBuilder = new StringBuilder("Hello World!");
+ MyStringBuilder.Replace('!', '?');
+ Console.WriteLine(MyStringBuilder);
+ }
+}
+// The example displays the following output:
+// Hello World?
+//
diff --git a/snippets/visualbasic/System.Text/Encoding/Overview/Project.vbproj b/snippets/visualbasic/System.Text/Encoding/Overview/Project.vbproj
new file mode 100644
index 00000000000..874c98f3477
--- /dev/null
+++ b/snippets/visualbasic/System.Text/Encoding/Overview/Project.vbproj
@@ -0,0 +1,8 @@
+
+
+
+ Library
+ net10.0
+
+
+
diff --git a/snippets/visualbasic/System.Text/Encoding/Overview/convert.vb b/snippets/visualbasic/System.Text/Encoding/Overview/convert.vb
index 20f3dbe6698..c35aa53e99d 100644
--- a/snippets/visualbasic/System.Text/Encoding/Overview/convert.vb
+++ b/snippets/visualbasic/System.Text/Encoding/Overview/convert.vb
@@ -1,8 +1,8 @@
'
Imports System.Text
-Class Example
- Shared Sub Main()
+Class Example1
+ Shared Sub Run()
Dim unicodeString As String = "This string contains the unicode character Pi (" & ChrW(&H03A0) & ")"
' Create two different encodings.
diff --git a/snippets/visualbasic/System.Text/Encoding/Overview/getencoding1.vb b/snippets/visualbasic/System.Text/Encoding/Overview/getencoding1.vb
new file mode 100644
index 00000000000..07a785983e5
--- /dev/null
+++ b/snippets/visualbasic/System.Text/Encoding/Overview/getencoding1.vb
@@ -0,0 +1,90 @@
+' Visual Basic .NET Document
+Option Strict On
+
+'
+Imports System.Text
+
+Module Example2
+ Public Sub Run()
+ Dim enc As Encoding = Encoding.GetEncoding(1253)
+ Dim altEnc As Encoding = Encoding.GetEncoding("windows-1253")
+ Console.WriteLine("{0} = Code Page {1}: {2}", enc.EncodingName,
+ altEnc.CodePage, enc.Equals(altEnc))
+ Dim greekAlphabet As String = "Α α Β β Γ γ Δ δ Ε ε Ζ ζ Η η " +
+ "Θ θ Ι ι Κ κ Λ λ Μ μ Ν ν Ξ ξ " +
+ "Ο ο Π π Ρ ρ Σ σ ς Τ τ Υ υ " +
+ "Φ φ Χ χ Ψ ψ Ω ω"
+ Console.OutputEncoding = Encoding.UTF8
+ Dim bytes() As Byte = enc.GetBytes(greekAlphabet)
+ Console.WriteLine("{0,-12} {1,20} {2,20:X2}", "Character",
+ "Unicode Code Point", "Code Page 1253")
+ For ctr As Integer = 0 To bytes.Length - 1
+ If greekAlphabet(ctr).Equals(" "c) Then Continue For
+
+ Console.WriteLine("{0,-12} {1,20} {2,20:X2}", greekAlphabet(ctr),
+ GetCodePoint(greekAlphabet(ctr)), bytes(ctr))
+ Next
+
+ End Sub
+
+ Private Function GetCodePoint(ch As String) As String
+ Dim retVal As String = "u+"
+ Dim bytes() As Byte = Encoding.Unicode.GetBytes(ch)
+ For ctr As Integer = bytes.Length - 1 To 0 Step -1
+ retVal += bytes(ctr).ToString("X2")
+ Next
+ Return retVal
+ End Function
+End Module
+' The example displays the following output:
+' Character Unicode Code Point Code Page 1253
+' Α u+0391 C1
+' α u+03B1 E1
+' Β u+0392 C2
+' β u+03B2 E2
+' Γ u+0393 C3
+' γ u+03B3 E3
+' Δ u+0394 C4
+' δ u+03B4 E4
+' Ε u+0395 C5
+' ε u+03B5 E5
+' Ζ u+0396 C6
+' ζ u+03B6 E6
+' Η u+0397 C7
+' η u+03B7 E7
+' Θ u+0398 C8
+' θ u+03B8 E8
+' Ι u+0399 C9
+' ι u+03B9 E9
+' Κ u+039A CA
+' κ u+03BA EA
+' Λ u+039B CB
+' λ u+03BB EB
+' Μ u+039C CC
+' μ u+03BC EC
+' Ν u+039D CD
+' ν u+03BD ED
+' Ξ u+039E CE
+' ξ u+03BE EE
+' Ο u+039F CF
+' ο u+03BF EF
+' Π u+03A0 D0
+' π u+03C0 F0
+' Ρ u+03A1 D1
+' ρ u+03C1 F1
+' Σ u+03A3 D3
+' σ u+03C3 F3
+' ς u+03C2 F2
+' Τ u+03A4 D4
+' τ u+03C4 F4
+' Υ u+03A5 D5
+' υ u+03C5 F5
+' Φ u+03A6 D6
+' φ u+03C6 F6
+' Χ u+03A7 D7
+' χ u+03C7 F7
+' Ψ u+03A8 D8
+' ψ u+03C8 F8
+' Ω u+03A9 D9
+' ω u+03C9 F9
+'
diff --git a/snippets/visualbasic/System.Text/StringBuilder/Overview/Project.vbproj b/snippets/visualbasic/System.Text/StringBuilder/Overview/Project.vbproj
new file mode 100644
index 00000000000..874c98f3477
--- /dev/null
+++ b/snippets/visualbasic/System.Text/StringBuilder/Overview/Project.vbproj
@@ -0,0 +1,8 @@
+
+
+
+ Library
+ net10.0
+
+
+
diff --git a/snippets/visualbasic/System.Text/StringBuilder/Overview/call1.vb b/snippets/visualbasic/System.Text/StringBuilder/Overview/call1.vb
new file mode 100644
index 00000000000..71c9e10dac0
--- /dev/null
+++ b/snippets/visualbasic/System.Text/StringBuilder/Overview/call1.vb
@@ -0,0 +1,19 @@
+' Visual Basic .NET Document
+Option Strict On
+
+'
+Imports System.Text
+
+Module Example2
+ Public Sub Main()
+ Dim sb As New StringBuilder()
+ sb.Append("This is the beginning of a sentence, ")
+ sb.Replace("the beginning of ", "")
+ sb.Insert(sb.ToString().IndexOf("a ") + 2, "complete ")
+ sb.Replace(",", ".")
+ Console.WriteLine(sb.ToString())
+ End Sub
+End Module
+' The example displays the following output:
+' This is a complete sentence.
+'
diff --git a/snippets/visualbasic/System.Text/StringBuilder/Overview/call2.vb b/snippets/visualbasic/System.Text/StringBuilder/Overview/call2.vb
new file mode 100644
index 00000000000..358d0a456b4
--- /dev/null
+++ b/snippets/visualbasic/System.Text/StringBuilder/Overview/call2.vb
@@ -0,0 +1,17 @@
+' Visual Basic .NET Document
+Option Strict On
+
+'
+Imports System.Text
+
+Module Example3
+ Public Sub Main()
+ Dim sb As New StringBuilder("This is the beginning of a sentence, ")
+ sb.Replace("the beginning of ", "").Insert(sb.ToString().IndexOf("a ") + 2,
+ "complete ").Replace(", ", ".")
+ Console.WriteLine(sb.ToString())
+ End Sub
+End Module
+' The example displays the following output:
+' This is a complete sentence.
+'
diff --git a/snippets/visualbasic/System.Text/StringBuilder/Overview/chars1.vb b/snippets/visualbasic/System.Text/StringBuilder/Overview/chars1.vb
new file mode 100644
index 00000000000..68f7824256a
--- /dev/null
+++ b/snippets/visualbasic/System.Text/StringBuilder/Overview/chars1.vb
@@ -0,0 +1,46 @@
+' Visual Basic .NET Document
+Option Strict On
+
+'
+Imports System.Globalization
+Imports System.Text
+
+Module Example4
+ Public Sub Main()
+ Dim rnd As New Random()
+ Dim sb As New StringBuilder()
+
+ ' Generate 10 random numbers and store them in a StringBuilder.
+ For ctr As Integer = 0 To 9
+ sb.Append(rnd.Next().ToString("N5"))
+ Next
+ Console.WriteLine("The original string:")
+ Console.WriteLine(sb.ToString())
+ Console.WriteLine()
+
+ ' Decrease each number by one.
+ For ctr As Integer = 0 To sb.Length - 1
+ If Char.GetUnicodeCategory(sb(ctr)) = UnicodeCategory.DecimalDigitNumber Then
+ Dim number As Integer = CType(Char.GetNumericValue(sb(ctr)), Integer)
+ number -= 1
+ If number < 0 Then number = 9
+
+ sb(ctr) = number.ToString()(0)
+ End If
+ Next
+ Console.WriteLine("The new string:")
+ Console.WriteLine(sb.ToString())
+ End Sub
+End Module
+' The example displays the following output:
+' The original string:
+' 1,457,531,530.00000940,522,609.000001,668,113,564.000001,998,992,883.000001,792,660,834.00
+' 000101,203,251.000002,051,183,075.000002,066,000,067.000001,643,701,043.000001,702,382,508
+' .00000
+'
+' The new string:
+' 0,346,420,429.99999839,411,598.999990,557,002,453.999990,887,881,772.999990,681,559,723.99
+' 999090,192,140.999991,940,072,964.999991,955,999,956.999990,532,690,932.999990,691,271,497
+' .99999
+'
+
diff --git a/snippets/visualbasic/System.Text/StringBuilder/Overview/default1.vb b/snippets/visualbasic/System.Text/StringBuilder/Overview/default1.vb
new file mode 100644
index 00000000000..60388e491b3
--- /dev/null
+++ b/snippets/visualbasic/System.Text/StringBuilder/Overview/default1.vb
@@ -0,0 +1,43 @@
+' Visual Basic .NET Document
+Option Strict On
+
+'
+Imports System.Reflection
+Imports System.Text
+
+Module Example5
+ Public Sub Main()
+ Dim sb As New StringBuilder()
+ ShowSBInfo(sb)
+ sb.Append("This is a sentence.")
+ ShowSBInfo(sb)
+ For ctr As Integer = 0 To 10
+ sb.Append("This is an additional sentence.")
+ ShowSBInfo(sb)
+ Next
+ End Sub
+
+ Public Sub ShowSBInfo(sb As StringBuilder)
+ For Each prop In sb.GetType().GetProperties
+ If prop.GetIndexParameters().Length = 0 Then
+ Console.Write("{0}: {1:N0} ", prop.Name, prop.GetValue(sb))
+ End If
+ Next
+ Console.WriteLine()
+ End Sub
+End Module
+' The example displays the following output:
+' Capacity: 16 MaxCapacity: 2,147,483,647 Length: 0
+' Capacity: 32 MaxCapacity: 2,147,483,647 Length: 19
+' Capacity: 64 MaxCapacity: 2,147,483,647 Length: 50
+' Capacity: 128 MaxCapacity: 2,147,483,647 Length: 81
+' Capacity: 128 MaxCapacity: 2,147,483,647 Length: 112
+' Capacity: 256 MaxCapacity: 2,147,483,647 Length: 143
+' Capacity: 256 MaxCapacity: 2,147,483,647 Length: 174
+' Capacity: 256 MaxCapacity: 2,147,483,647 Length: 205
+' Capacity: 256 MaxCapacity: 2,147,483,647 Length: 236
+' Capacity: 512 MaxCapacity: 2,147,483,647 Length: 267
+' Capacity: 512 MaxCapacity: 2,147,483,647 Length: 298
+' Capacity: 512 MaxCapacity: 2,147,483,647 Length: 329
+' Capacity: 512 MaxCapacity: 2,147,483,647 Length: 360
+'
diff --git a/snippets/visualbasic/System.Text/StringBuilder/Overview/delete1.vb b/snippets/visualbasic/System.Text/StringBuilder/Overview/delete1.vb
new file mode 100644
index 00000000000..905d4bd6f64
--- /dev/null
+++ b/snippets/visualbasic/System.Text/StringBuilder/Overview/delete1.vb
@@ -0,0 +1,44 @@
+' Visual Basic .NET Document
+Option Strict On
+
+'
+Imports System.Text
+
+Module Example6
+ Public Sub Main()
+ Dim sb As New StringBuilder("A StringBuilder object")
+ ShowSBInfo(sb)
+ ' Remove "object" from the text.
+ Dim textToRemove As String = "object"
+ Dim pos As Integer = sb.ToString().IndexOf(textToRemove)
+ If pos >= 0 Then
+ sb.Remove(pos, textToRemove.Length)
+ ShowSBInfo(sb)
+ End If
+ ' Clear the StringBuilder contents.
+ sb.Clear()
+ ShowSBInfo(sb)
+ End Sub
+
+ Public Sub ShowSBInfo(sb As StringBuilder)
+ Console.WriteLine()
+ Console.WriteLine("Value: {0}", sb.ToString())
+ For Each prop In sb.GetType().GetProperties
+ If prop.GetIndexParameters().Length = 0 Then
+ Console.Write("{0}: {1:N0} ", prop.Name, prop.GetValue(sb))
+ End If
+ Next
+ Console.WriteLine()
+ End Sub
+End Module
+' The example displays the following output:
+' Value: A StringBuilder object
+' Capacity: 22 MaxCapacity: 2,147,483,647 Length: 22
+'
+' Value: A StringBuilder
+' Capacity: 22 MaxCapacity: 2,147,483,647 Length: 16
+'
+' Value:
+' Capacity: 22 MaxCapacity: 2,147,483,647 Length: 0
+'
+
diff --git a/snippets/visualbasic/System.Text/StringBuilder/Overview/expand1.vb b/snippets/visualbasic/System.Text/StringBuilder/Overview/expand1.vb
new file mode 100644
index 00000000000..6e400655e5f
--- /dev/null
+++ b/snippets/visualbasic/System.Text/StringBuilder/Overview/expand1.vb
@@ -0,0 +1,49 @@
+' Visual Basic .NET Document
+Option Strict On
+
+'
+Imports System.Text
+
+Module Example7
+ Public Sub Main()
+ ' Create a StringBuilder object with no text.
+ Dim sb As New StringBuilder()
+ ' Append some text.
+ sb.Append("*"c, 10).Append(" Adding Text to a StringBuilder Object ").Append("*"c, 10)
+ sb.AppendLine()
+ sb.AppendLine()
+ sb.AppendLine("Some code points and their corresponding characters:")
+ ' Append some formatted text.
+ For ctr = 50 To 60
+ sb.AppendFormat("{0,12:X4} {1,12}", ctr, Convert.ToChar(ctr))
+ sb.AppendLine()
+ Next
+ ' Find the end of the introduction to the column.
+ Dim pos As Integer = sb.ToString().IndexOf("characters:") + 11 +
+ Environment.NewLine.Length
+ ' Insert a column header.
+ sb.Insert(pos, String.Format("{2}{0,12} {1,12}{2}", "Code Unit",
+ "Character", vbCrLf))
+
+ ' Convert the StringBuilder to a string and display it.
+ Console.WriteLine(sb.ToString())
+ End Sub
+End Module
+' The example displays the following output:
+' ********** Adding Text to a StringBuilder Object **********
+'
+' Some code points and their corresponding characters:
+'
+' Code Unit Character
+' 0032 2
+' 0033 3
+' 0034 4
+' 0035 5
+' 0036 6
+' 0037 7
+' 0038 8
+' 0039 9
+' 003A :
+' 003B ;
+' 003C <
+'
diff --git a/snippets/visualbasic/System.Text/StringBuilder/Overview/instantiate1.vb b/snippets/visualbasic/System.Text/StringBuilder/Overview/instantiate1.vb
new file mode 100644
index 00000000000..a2ecb1f9a8c
--- /dev/null
+++ b/snippets/visualbasic/System.Text/StringBuilder/Overview/instantiate1.vb
@@ -0,0 +1,49 @@
+' Visual Basic .NET Document
+Option Strict On
+
+'
+Imports System.Text
+
+Module Example8
+ Public Sub Main()
+ Dim value As String = "An ordinary string"
+ Dim index As Integer = value.IndexOf("An ") + 3
+ Dim capacity As Integer = &HFFFF
+
+ ' Instantiate a StringBuilder from a string.
+ Dim sb1 As New StringBuilder(value)
+ ShowSBInfo(sb1)
+
+ ' Instantiate a StringBuilder from string and define a capacity.
+ Dim sb2 As New StringBuilder(value, capacity)
+ ShowSBInfo(sb2)
+
+ ' Instantiate a StringBuilder from substring and define a capacity.
+ Dim sb3 As New StringBuilder(value, index,
+ value.Length - index,
+ capacity)
+ ShowSBInfo(sb3)
+ End Sub
+
+ Public Sub ShowSBInfo(sb As StringBuilder)
+ Console.WriteLine()
+ Console.WriteLine("Value: {0}", sb.ToString())
+ For Each prop In sb.GetType().GetProperties
+ If prop.GetIndexParameters().Length = 0 Then
+ Console.Write("{0}: {1:N0} ", prop.Name, prop.GetValue(sb))
+ End If
+ Next
+ Console.WriteLine()
+ End Sub
+End Module
+' The example displays the following output:
+' Value: An ordinary string
+' Capacity: 18 MaxCapacity: 2,147,483,647 Length: 18
+'
+' Value: An ordinary string
+' Capacity: 65,535 MaxCapacity: 2,147,483,647 Length: 18
+'
+' Value: ordinary string
+' Capacity: 65,535 MaxCapacity: 2,147,483,647 Length: 15
+'
+
diff --git a/snippets/visualbasic/System.Text/StringBuilder/Overview/pattern1.vb b/snippets/visualbasic/System.Text/StringBuilder/Overview/pattern1.vb
new file mode 100644
index 00000000000..bfef80bcabc
--- /dev/null
+++ b/snippets/visualbasic/System.Text/StringBuilder/Overview/pattern1.vb
@@ -0,0 +1,60 @@
+' Visual Basic .NET Document
+Option Strict On
+
+'
+Imports System.Text
+
+Module Example9
+ Public Sub Main()
+ Dim rnd As New Random()
+ Dim tempF() As String = {"47.6F", "51.3F", "49.5F", "62.3F"}
+ Dim tempC() As String = {"21.2C", "16.1C", "23.5C", "22.9C"}
+ Dim temps()() As String = {tempF, tempC}
+
+ Dim sb As StringBuilder = New StringBuilder()
+ Dim f As New StringBuilderFinder(sb, "F")
+ Dim baseDate As New DateTime(2013, 5, 1)
+ Dim temperatures() As String = temps(rnd.Next(2))
+ Dim isFahrenheit As Boolean = False
+ For Each temperature In temperatures
+ If isFahrenheit Then
+ sb.AppendFormat("{0:d}: {1}{2}", baseDate, temperature, vbCrLf)
+ Else
+ isFahrenheit = f.SearchAndAppend(String.Format("{0:d}: {1}{2}",
+ baseDate, temperature, vbCrLf))
+ End If
+ baseDate = baseDate.AddDays(1)
+ Next
+ If isFahrenheit Then
+ sb.Insert(0, "Average Daily Temperature in Degrees Fahrenheit")
+ sb.Insert(47, vbCrLf + vbCrLf)
+ Else
+ sb.Insert(0, "Average Daily Temperature in Degrees Celsius")
+ sb.Insert(44, vbCrLf + vbCrLf)
+ End If
+ Console.WriteLine(sb.ToString())
+ End Sub
+End Module
+
+Public Class StringBuilderFinder
+ Private sb As StringBuilder
+ Private text As String
+
+ Public Sub New(sb As StringBuilder, textToFind As String)
+ Me.sb = sb
+ text = textToFind
+ End Sub
+
+ Public Function SearchAndAppend(stringToSearch As String) As Boolean
+ sb.Append(stringToSearch)
+ Return stringToSearch.Contains(text)
+ End Function
+End Class
+' The example displays output similar to the following:
+' Average Daily Temperature in Degrees Celsius
+'
+' 5/1/2013: 21.2C
+' 5/2/2013: 16.1C
+' 5/3/2013: 23.5C
+' 5/4/2013: 22.9C
+'
diff --git a/snippets/visualbasic/System.Text/StringBuilder/Overview/pattern2.vb b/snippets/visualbasic/System.Text/StringBuilder/Overview/pattern2.vb
new file mode 100644
index 00000000000..0fa2ece1e7b
--- /dev/null
+++ b/snippets/visualbasic/System.Text/StringBuilder/Overview/pattern2.vb
@@ -0,0 +1,43 @@
+' Visual Basic .NET Document
+Option Strict On
+
+'
+Imports System.Text
+Imports System.Text.RegularExpressions
+
+Module Example10
+ Public Sub Main()
+ ' Create a StringBuilder object with 4 successive occurrences
+ ' of each character in the English alphabet.
+ Dim sb As New StringBuilder()
+ For ctr As UShort = AscW("a") To AscW("z")
+ sb.Append(ChrW(ctr), 4)
+ Next
+ ' Create a parallel string object.
+ Dim sbString As String = sb.ToString()
+ ' Determine where each new character sequence begins.
+ Dim pattern As String = "(\w)\1+"
+ Dim matches As MatchCollection = Regex.Matches(sbString, pattern)
+
+ ' Uppercase the first occurrence of the sequence, and separate it
+ ' from the previous sequence by an underscore character.
+ For ctr As Integer = matches.Count - 1 To 0 Step -1
+ Dim m As Match = matches(ctr)
+ sb.Chars(m.Index) = Char.ToUpper(sb.Chars(m.Index))
+ If m.Index > 0 Then sb.Insert(m.Index, "_")
+ Next
+ ' Display the resulting string.
+ sbString = sb.ToString()
+ Dim line As Integer = 0
+ Do
+ Dim nChars As Integer = If(line * 80 + 79 <= sbString.Length,
+ 80, sbString.Length - line * 80)
+ Console.WriteLine(sbString.Substring(line * 80, nChars))
+ line += 1
+ Loop While line * 80 < sbString.Length
+ End Sub
+End Module
+' The example displays the following output:
+' Aaaa_Bbbb_Cccc_Dddd_Eeee_Ffff_Gggg_Hhhh_Iiii_Jjjj_Kkkk_Llll_Mmmm_Nnnn_Oooo_Pppp_
+' Qqqq_Rrrr_Ssss_Tttt_Uuuu_Vvvv_Wwww_Xxxx_Yyyy_Zzzz
+'
diff --git a/snippets/visualbasic/System.Text/StringBuilder/Overview/pattern3.vb b/snippets/visualbasic/System.Text/StringBuilder/Overview/pattern3.vb
new file mode 100644
index 00000000000..7ecbaa54107
--- /dev/null
+++ b/snippets/visualbasic/System.Text/StringBuilder/Overview/pattern3.vb
@@ -0,0 +1,42 @@
+' Visual Basic .NET Document
+Option Strict On
+
+'
+Imports System.Text
+
+Module Example11
+ Public Sub Main()
+ ' Create a StringBuilder object with 4 successive occurrences
+ ' of each character in the English alphabet.
+ Dim sb As New StringBuilder()
+ For ctr As UShort = AscW("a") To AscW("z")
+ sb.Append(ChrW(ctr), 4)
+ Next
+ ' Iterate the text to determine when a new character sequence occurs.
+ Dim position As Integer = 0
+ Dim current As Char = ChrW(0)
+ Do
+ If sb(position) <> current Then
+ current = sb(position)
+ sb(position) = Char.ToUpper(sb(position))
+ If position > 0 Then sb.Insert(position, "_")
+ position += 2
+ Else
+ position += 1
+ End If
+ Loop While position <= sb.Length - 1
+ ' Display the resulting string.
+ Dim sbString As String = sb.ToString()
+ Dim line As Integer = 0
+ Do
+ Dim nChars As Integer = If(line * 80 + 79 <= sbString.Length,
+ 80, sbString.Length - line * 80)
+ Console.WriteLine(sbString.Substring(line * 80, nChars))
+ line += 1
+ Loop While line * 80 < sbString.Length
+ End Sub
+End Module
+' The example displays the following output:
+' Aaaa_Bbbb_Cccc_Dddd_Eeee_Ffff_Gggg_Hhhh_Iiii_Jjjj_Kkkk_Llll_Mmmm_Nnnn_Oooo_Pppp_
+' Qqqq_Rrrr_Ssss_Tttt_Uuuu_Vvvv_Wwww_Xxxx_Yyyy_Zzzz
+'
diff --git a/snippets/visualbasic/System.Text/StringBuilder/Overview/pattern4.vb b/snippets/visualbasic/System.Text/StringBuilder/Overview/pattern4.vb
new file mode 100644
index 00000000000..9fb52dbd596
--- /dev/null
+++ b/snippets/visualbasic/System.Text/StringBuilder/Overview/pattern4.vb
@@ -0,0 +1,40 @@
+' Visual Basic .NET Document
+Option Strict On
+
+'
+Imports System.Text
+Imports System.Text.RegularExpressions
+
+Module Example12
+ Public Sub Main()
+ ' Create a StringBuilder object with 4 successive occurrences
+ ' of each character in the English alphabet.
+ Dim sb As New StringBuilder()
+ For ctr As UShort = AscW("a") To AscW("z")
+ sb.Append(ChrW(ctr), 4)
+ Next
+ ' Convert it to a string.
+ Dim sbString As String = sb.ToString()
+
+ ' Use a regex to uppercase the first occurrence of the sequence,
+ ' and separate it from the previous sequence by an underscore.
+ Dim pattern As String = "(\w)(\1+)"
+ sbString = Regex.Replace(sbString, pattern,
+ Function(m) If(m.Index > 0, "_", "") +
+ m.Groups(1).Value.ToUpper +
+ m.Groups(2).Value)
+
+ ' Display the resulting string.
+ Dim line As Integer = 0
+ Do
+ Dim nChars As Integer = If(line * 80 + 79 <= sbString.Length,
+ 80, sbString.Length - line * 80)
+ Console.WriteLine(sbString.Substring(line * 80, nChars))
+ line += 1
+ Loop While line * 80 < sbString.Length
+ End Sub
+End Module
+' The example displays the following output:
+' Aaaa_Bbbb_Cccc_Dddd_Eeee_Ffff_Gggg_Hhhh_Iiii_Jjjj_Kkkk_Llll_Mmmm_Nnnn_Oooo_Pppp_
+' Qqqq_Rrrr_Ssss_Tttt_Uuuu_Vvvv_Wwww_Xxxx_Yyyy_Zzzz
+'
diff --git a/snippets/visualbasic/System.Text/StringBuilder/Overview/replace1.vb b/snippets/visualbasic/System.Text/StringBuilder/Overview/replace1.vb
new file mode 100644
index 00000000000..7da78f82ca4
--- /dev/null
+++ b/snippets/visualbasic/System.Text/StringBuilder/Overview/replace1.vb
@@ -0,0 +1,16 @@
+' Visual Basic .NET Document
+Option Strict On
+
+'
+Imports System.Text
+
+Module Example
+ Public Sub Main()
+ Dim MyStringBuilder As New StringBuilder("Hello World!")
+ MyStringBuilder.Replace("!"c, "?"c)
+ Console.WriteLine(MyStringBuilder)
+ End Sub
+End Module
+' The example displays the following output:
+' Hello World?
+'
diff --git a/snippets/visualbasic/System.Threading.Tasks/Task/Overview/Project.vbproj b/snippets/visualbasic/System.Threading.Tasks/Task/Overview/Project.vbproj
new file mode 100644
index 00000000000..874c98f3477
--- /dev/null
+++ b/snippets/visualbasic/System.Threading.Tasks/Task/Overview/Project.vbproj
@@ -0,0 +1,8 @@
+
+
+
+ Library
+ net10.0
+
+
+
diff --git a/snippets/visualbasic/System.Threading.Tasks/Task/Overview/Wait1.vb b/snippets/visualbasic/System.Threading.Tasks/Task/Overview/Wait1.vb
new file mode 100644
index 00000000000..914b7bce249
--- /dev/null
+++ b/snippets/visualbasic/System.Threading.Tasks/Task/Overview/Wait1.vb
@@ -0,0 +1,24 @@
+' Visual Basic .NET Document
+Option Strict On
+
+'
+Imports System.Threading
+Imports System.Threading.Tasks
+
+Module Example4
+ Public Sub Main()
+ ' Wait on a single task with no timeout specified.
+ Dim taskA = Task.Run(Sub() Thread.Sleep(2000))
+ Console.WriteLine("taskA Status: {0}", taskA.Status)
+ Try
+ taskA.Wait()
+ Console.WriteLine("taskA Status: {0}", taskA.Status)
+ Catch e As AggregateException
+ Console.WriteLine("Exception in taskA.")
+ End Try
+ End Sub
+End Module
+' The example displays output like the following:
+' taskA Status: WaitingToRun
+' taskA Status: RanToCompletion
+'
diff --git a/snippets/visualbasic/System.Threading.Tasks/Task/Overview/Wait2.vb b/snippets/visualbasic/System.Threading.Tasks/Task/Overview/Wait2.vb
new file mode 100644
index 00000000000..5831bede59b
--- /dev/null
+++ b/snippets/visualbasic/System.Threading.Tasks/Task/Overview/Wait2.vb
@@ -0,0 +1,28 @@
+' Visual Basic .NET Document
+Option Strict On
+
+'
+Imports System.Threading
+Imports System.Threading.Tasks
+
+Module Example5
+ Public Sub Main()
+ ' Wait on a single task with a timeout specified.
+ Dim taskA As Task = Task.Run(Sub() Thread.Sleep(2000))
+ Try
+ taskA.Wait(1000) ' Wait for 1 second.
+ Dim completed As Boolean = taskA.IsCompleted
+ Console.WriteLine("Task.Completed: {0}, Status: {1}",
+ completed, taskA.Status)
+ If Not completed Then
+ Console.WriteLine("Timed out before task A completed.")
+ End If
+ Catch e As AggregateException
+ Console.WriteLine("Exception in taskA.")
+ End Try
+ End Sub
+End Module
+' The example displays the following output:
+' Task A completed: False, Status: Running
+' Timed out before task A completed.
+'
diff --git a/snippets/visualbasic/System.Threading.Tasks/Task/Overview/WaitAll1.vb b/snippets/visualbasic/System.Threading.Tasks/Task/Overview/WaitAll1.vb
new file mode 100644
index 00000000000..fc512ca31a2
--- /dev/null
+++ b/snippets/visualbasic/System.Threading.Tasks/Task/Overview/WaitAll1.vb
@@ -0,0 +1,42 @@
+' Visual Basic .NET Document
+Option Strict On
+
+'
+Imports System.Threading
+Imports System.Threading.Tasks
+
+Module Example6
+ Public Sub Main()
+ ' Wait for all tasks to complete.
+ Dim tasks(9) As Task
+ For i As Integer = 0 To 9
+ tasks(i) = Task.Run(Sub() Thread.Sleep(2000))
+ Next
+ Try
+ Task.WaitAll(tasks)
+ Catch ae As AggregateException
+ Console.WriteLine("One or more exceptions occurred: ")
+ For Each ex In ae.Flatten().InnerExceptions
+ Console.WriteLine(" {0}", ex.Message)
+ Next
+ End Try
+
+ Console.WriteLine("Status of completed tasks:")
+ For Each t In tasks
+ Console.WriteLine(" Task #{0}: {1}", t.Id, t.Status)
+ Next
+ End Sub
+End Module
+' The example displays the following output:
+' Status of completed tasks:
+' Task #2: RanToCompletion
+' Task #1: RanToCompletion
+' Task #3: RanToCompletion
+' Task #4: RanToCompletion
+' Task #6: RanToCompletion
+' Task #5: RanToCompletion
+' Task #7: RanToCompletion
+' Task #8: RanToCompletion
+' Task #9: RanToCompletion
+' Task #10: RanToCompletion
+'
diff --git a/snippets/visualbasic/System.Threading.Tasks/Task/Overview/WaitAll2.vb b/snippets/visualbasic/System.Threading.Tasks/Task/Overview/WaitAll2.vb
new file mode 100644
index 00000000000..91cea251e4b
--- /dev/null
+++ b/snippets/visualbasic/System.Threading.Tasks/Task/Overview/WaitAll2.vb
@@ -0,0 +1,98 @@
+' Visual Basic .NET Document
+Option Strict On
+
+'
+Imports System.Threading
+Imports System.Threading.Tasks
+
+Module Example7
+ Public Sub Main()
+ ' Create a cancellation token and cancel it.
+ Dim source1 As New CancellationTokenSource()
+ Dim token1 As CancellationToken = source1.Token
+ source1.Cancel()
+ ' Create a cancellation token for later cancellation.
+ Dim source2 As New CancellationTokenSource()
+ Dim token2 As CancellationToken = source2.Token
+
+ ' Create a series of tasks that will complete, be cancelled,
+ ' timeout, or throw an exception.
+ Dim tasks(11) As Task
+ For i As Integer = 0 To 11
+ Select Case i Mod 4
+ ' Task should run to completion.
+ Case 0
+ tasks(i) = Task.Run(Sub() Thread.Sleep(2000))
+ ' Task should be set to canceled state.
+ Case 1
+ tasks(i) = Task.Run(Sub() Thread.Sleep(2000), token1)
+ Case 2
+ ' Task should throw an exception.
+ tasks(i) = Task.Run(Sub()
+ Throw New NotSupportedException()
+ End Sub)
+ Case 3
+ ' Task should examine cancellation token.
+ tasks(i) = Task.Run(Sub()
+ Thread.Sleep(2000)
+ If token2.IsCancellationRequested Then
+ token2.ThrowIfCancellationRequested()
+ End If
+ Thread.Sleep(500)
+ End Sub, token2)
+ End Select
+ Next
+ Thread.Sleep(250)
+ source2.Cancel()
+
+ Try
+ Task.WaitAll(tasks)
+ Catch ae As AggregateException
+ Console.WriteLine("One or more exceptions occurred:")
+ For Each ex In ae.InnerExceptions
+ Console.WriteLine(" {0}: {1}", ex.GetType().Name, ex.Message)
+ Next
+ End Try
+ Console.WriteLine()
+
+ Console.WriteLine("Status of tasks:")
+ For Each t In tasks
+ Console.WriteLine(" Task #{0}: {1}", t.Id, t.Status)
+ If t.Exception IsNot Nothing Then
+ For Each ex In t.Exception.InnerExceptions
+ Console.WriteLine(" {0}: {1}", ex.GetType().Name,
+ ex.Message)
+ Next
+ End If
+ Next
+ End Sub
+End Module
+' The example displays output like the following:
+' One or more exceptions occurred:
+' TaskCanceledException: A task was canceled.
+' NotSupportedException: Specified method is not supported.
+' TaskCanceledException: A task was canceled.
+' TaskCanceledException: A task was canceled.
+' NotSupportedException: Specified method is not supported.
+' TaskCanceledException: A task was canceled.
+' TaskCanceledException: A task was canceled.
+' NotSupportedException: Specified method is not supported.
+' TaskCanceledException: A task was canceled.
+'
+' Status of tasks:
+' Task #13: RanToCompletion
+' Task #1: Canceled
+' Task #3: Faulted
+' NotSupportedException: Specified method is not supported.
+' Task #8: Canceled
+' Task #14: RanToCompletion
+' Task #4: Canceled
+' Task #6: Faulted
+' NotSupportedException: Specified method is not supported.
+' Task #7: Canceled
+' Task #15: RanToCompletion
+' Task #9: Canceled
+' Task #11: Faulted
+' NotSupportedException: Specified method is not supported.
+' Task #12: Canceled
+'
diff --git a/snippets/visualbasic/System.Threading.Tasks/Task/Overview/WaitAny1.vb b/snippets/visualbasic/System.Threading.Tasks/Task/Overview/WaitAny1.vb
new file mode 100644
index 00000000000..31c1dbeb1e5
--- /dev/null
+++ b/snippets/visualbasic/System.Threading.Tasks/Task/Overview/WaitAny1.vb
@@ -0,0 +1,36 @@
+' Visual Basic .NET Document
+Option Strict On
+
+'
+Imports System.Threading
+Imports System.Threading.Tasks
+
+Module Example8
+ Public Sub Main()
+ Dim tasks(2) As Task
+ Dim rnd As New Random()
+ For ctr As Integer = 0 To 2
+ tasks(ctr) = Task.Run(Sub() Thread.Sleep(rnd.Next(500, 3000)))
+ Next
+
+ Try
+ Dim index As Integer = Task.WaitAny(tasks)
+ Console.WriteLine("Task #{0} completed first.", tasks(index).Id)
+ Console.WriteLine()
+ Console.WriteLine("Status of all tasks:")
+ For Each t In tasks
+ Console.WriteLine(" Task #{0}: {1}", t.Id, t.Status)
+ Next
+ Catch e As AggregateException
+ Console.WriteLine("An exception occurred.")
+ End Try
+ End Sub
+End Module
+' The example displays output like the following:
+' Task #1 completed first.
+'
+' Status of all tasks:
+' Task #3: Running
+' Task #1: RanToCompletion
+' Task #4: Running
+'
diff --git a/snippets/visualbasic/System.Threading.Tasks/Task/Overview/run1.vb b/snippets/visualbasic/System.Threading.Tasks/Task/Overview/run1.vb
new file mode 100644
index 00000000000..1c5ed25f062
--- /dev/null
+++ b/snippets/visualbasic/System.Threading.Tasks/Task/Overview/run1.vb
@@ -0,0 +1,22 @@
+' Visual Basic .NET Document
+Option Strict On
+
+'
+Imports System.Threading.Tasks
+
+Module Example1
+ Public Sub Main()
+ Dim t As Task = Task.Run(Sub()
+ ' Just loop.
+ Dim ctr As Integer = 0
+ For ctr = 0 To 1000000
+ Next
+ Console.WriteLine("Finished {0} loop iterations",
+ ctr)
+ End Sub)
+ t.Wait()
+ End Sub
+End Module
+' The example displays the following output:
+' Finished 1000001 loop iterations
+'
diff --git a/snippets/visualbasic/System.Threading.Tasks/Task/Overview/startnew.vb b/snippets/visualbasic/System.Threading.Tasks/Task/Overview/startnew.vb
new file mode 100644
index 00000000000..855e0f8297b
--- /dev/null
+++ b/snippets/visualbasic/System.Threading.Tasks/Task/Overview/startnew.vb
@@ -0,0 +1,54 @@
+'
+Imports System.Threading
+Imports System.Threading.Tasks
+
+Module Example2
+ Public Sub Main()
+ Dim action As Action(Of Object) =
+ Sub(obj As Object)
+ Console.WriteLine("Task={0}, obj={1}, Thread={2}",
+ Task.CurrentId, obj,
+ Thread.CurrentThread.ManagedThreadId)
+ End Sub
+
+ ' Construct an unstarted task
+ Dim t1 As New Task(action, "alpha")
+
+ ' Construct a started task
+ Dim t2 As Task = Task.Factory.StartNew(action, "beta")
+ ' Block the main thread to demonstrate that t2 is executing
+ t2.Wait()
+
+ ' Launch t1
+ t1.Start()
+ Console.WriteLine("t1 has been launched. (Main Thread={0})",
+ Thread.CurrentThread.ManagedThreadId)
+ ' Wait for the task to finish.
+ t1.Wait()
+
+ ' Construct a started task using Task.Run.
+ Dim taskData As String = "delta"
+ Dim t3 As Task = Task.Run(Sub()
+ Console.WriteLine("Task={0}, obj={1}, Thread={2}",
+ Task.CurrentId, taskData,
+ Thread.CurrentThread.ManagedThreadId)
+ End Sub)
+ ' Wait for the task to finish.
+ t3.Wait()
+
+ ' Construct an unstarted task
+ Dim t4 As New Task(action, "gamma")
+ ' Run it synchronously
+ t4.RunSynchronously()
+ ' Although the task was run synchronously, it is a good practice
+ ' to wait for it in the event exceptions were thrown by the task.
+ t4.Wait()
+ End Sub
+End Module
+' The example displays output like the following:
+' Task=1, obj=beta, Thread=3
+' t1 has been launched. (Main Thread=1)
+' Task=2, obj=alpha, Thread=3
+' Task=3, obj=delta, Thread=3
+' Task=4, obj=gamma, Thread=1
+'
diff --git a/snippets/visualbasic/System.Threading.Tasks/Task/Overview/startnew1.vb b/snippets/visualbasic/System.Threading.Tasks/Task/Overview/startnew1.vb
new file mode 100644
index 00000000000..c8653513f1f
--- /dev/null
+++ b/snippets/visualbasic/System.Threading.Tasks/Task/Overview/startnew1.vb
@@ -0,0 +1,22 @@
+' Visual Basic .NET Document
+Option Strict On
+
+'
+Imports System.Threading.Tasks
+
+Module Example3
+ Public Sub Main()
+ Dim t As Task = Task.Factory.StartNew(Sub()
+ ' Just loop.
+ Dim ctr As Integer = 0
+ For ctr = 0 To 1000000
+ Next
+ Console.WriteLine("Finished {0} loop iterations",
+ ctr)
+ End Sub)
+ t.Wait()
+ End Sub
+End Module
+' The example displays the following output:
+' Finished 1000001 loop iterations
+'
diff --git a/snippets/visualbasic/System.Threading/Monitor/Overview/Pattern2.vb b/snippets/visualbasic/System.Threading/Monitor/Overview/Pattern2.vb
new file mode 100644
index 00000000000..1bb579c6cbc
--- /dev/null
+++ b/snippets/visualbasic/System.Threading/Monitor/Overview/Pattern2.vb
@@ -0,0 +1,32 @@
+' Visual Basic .NET Document
+Option Strict On
+
+Imports System.Runtime.CompilerServices
+Imports System.Threading
+
+Module Example5
+ Public Sub Main()
+ '
+ ' Define the lock object.
+ Dim obj As New Object()
+
+ ' Define the critical section.
+ Monitor.Enter(obj)
+ Try
+ ' Code to execute one thread at a time.
+
+ ' catch blocks go here.
+ Finally
+ Monitor.Exit(obj)
+ End Try
+ '
+ End Sub
+
+ '
+
+ Sub MethodToLock()
+ ' Method implementation.
+ End Sub
+ '
+End Module
+
diff --git a/snippets/visualbasic/System.Threading/Monitor/Overview/Project.vbproj b/snippets/visualbasic/System.Threading/Monitor/Overview/Project.vbproj
new file mode 100644
index 00000000000..874c98f3477
--- /dev/null
+++ b/snippets/visualbasic/System.Threading/Monitor/Overview/Project.vbproj
@@ -0,0 +1,8 @@
+
+
+
+ Library
+ net10.0
+
+
+
diff --git a/snippets/visualbasic/System.Threading/Monitor/Overview/badbox1.vb b/snippets/visualbasic/System.Threading/Monitor/Overview/badbox1.vb
new file mode 100644
index 00000000000..d044f7b82bb
--- /dev/null
+++ b/snippets/visualbasic/System.Threading/Monitor/Overview/badbox1.vb
@@ -0,0 +1,47 @@
+' Visual Basic .NET Document
+Option Strict On
+
+'
+Imports System.Collections.Generic
+Imports System.Threading
+Imports System.Threading.Tasks
+
+Module Example2
+ Public Sub Main()
+ Dim nTasks As Integer = 0
+ Dim o As Object = nTasks
+ Dim tasks As New List(Of Task)()
+
+ Try
+ For ctr As Integer = 0 To 9
+ tasks.Add(Task.Run(Sub()
+ ' Instead of doing some work, just sleep.
+ Thread.Sleep(250)
+ ' Increment the number of tasks.
+ Monitor.Enter(o)
+ Try
+ nTasks += 1
+ Finally
+ Monitor.Exit(o)
+ End Try
+ End Sub))
+ Next
+ Task.WaitAll(tasks.ToArray())
+ Console.WriteLine("{0} tasks started and executed.", nTasks)
+ Catch e As AggregateException
+ Dim msg As String = String.Empty
+ For Each ie In e.InnerExceptions
+ Console.WriteLine("{0}", ie.GetType().Name)
+ If Not msg.Contains(ie.Message) Then
+ msg += ie.Message + Environment.NewLine
+ End If
+ Next
+ Console.WriteLine(vbCrLf + "Exception Message(s):")
+ Console.WriteLine(msg)
+ End Try
+ End Sub
+End Module
+' The example displays the following output:
+' 10 tasks started and executed.
+'
+
diff --git a/snippets/visualbasic/System.Threading/Monitor/Overview/badlock1.vb b/snippets/visualbasic/System.Threading/Monitor/Overview/badlock1.vb
new file mode 100644
index 00000000000..423f706a8c4
--- /dev/null
+++ b/snippets/visualbasic/System.Threading/Monitor/Overview/badlock1.vb
@@ -0,0 +1,60 @@
+' Visual Basic .NET Document
+Option Strict On
+
+'
+Imports System.Collections.Generic
+Imports System.Threading
+Imports System.Threading.Tasks
+
+Module Example3
+ Public Sub Main()
+ Dim nTasks As Integer = 0
+ Dim tasks As New List(Of Task)()
+
+ Try
+ For ctr As Integer = 0 To 9
+ tasks.Add(Task.Run(Sub()
+ ' Instead of doing some work, just sleep.
+ Thread.Sleep(250)
+ ' Increment the number of tasks.
+ Monitor.Enter(nTasks)
+ Try
+ nTasks += 1
+ Finally
+ Monitor.Exit(nTasks)
+ End Try
+ End Sub))
+ Next
+ Task.WaitAll(tasks.ToArray())
+ Console.WriteLine("{0} tasks started and executed.", nTasks)
+ Catch e As AggregateException
+ Dim msg As String = String.Empty
+ For Each ie In e.InnerExceptions
+ Console.WriteLine("{0}", ie.GetType().Name)
+ If Not msg.Contains(ie.Message) Then
+ msg += ie.Message + Environment.NewLine
+ End If
+ Next
+ Console.WriteLine(vbCrLf + "Exception Message(s):")
+ Console.WriteLine(msg)
+ End Try
+ End Sub
+End Module
+' The example displays the following output:
+' SynchronizationLockException
+' SynchronizationLockException
+' SynchronizationLockException
+' SynchronizationLockException
+' SynchronizationLockException
+' SynchronizationLockException
+' SynchronizationLockException
+' SynchronizationLockException
+' SynchronizationLockException
+' SynchronizationLockException
+'
+' Exception Message(s):
+' Object synchronization method was called from an unsynchronized block of code.
+'
+
+
+
diff --git a/snippets/visualbasic/System.Threading/Monitor/Overview/example1.vb b/snippets/visualbasic/System.Threading/Monitor/Overview/example1.vb
new file mode 100644
index 00000000000..26508642524
--- /dev/null
+++ b/snippets/visualbasic/System.Threading/Monitor/Overview/example1.vb
@@ -0,0 +1,66 @@
+' Visual Basic .NET Document
+Option Strict On
+
+'
+Imports System.Collections.Generic
+Imports System.Threading
+Imports System.Threading.Tasks
+
+Module Example4
+ Public Sub Main()
+ Dim tasks As New List(Of Task)()
+ Dim rnd As New Random()
+ Dim total As Long = 0
+ Dim n As Integer = 0
+
+ For taskCtr As Integer = 0 To 9
+ tasks.Add(Task.Run(Sub()
+ Dim values(9999) As Integer
+ Dim taskTotal As Integer = 0
+ Dim taskN As Integer = 0
+ Dim ctr As Integer = 0
+ Monitor.Enter(rnd)
+ ' Generate 10,000 random integers.
+ For ctr = 0 To 9999
+ values(ctr) = rnd.Next(0, 1001)
+ Next
+ Monitor.Exit(rnd)
+ taskN = ctr
+ For Each value In values
+ taskTotal += value
+ Next
+
+ Console.WriteLine("Mean for task {0,2}: {1:N2} (N={2:N0})",
+ Task.CurrentId, taskTotal / taskN,
+ taskN)
+ Interlocked.Add(n, taskN)
+ Interlocked.Add(total, taskTotal)
+ End Sub))
+ Next
+
+ Try
+ Task.WaitAll(tasks.ToArray())
+ Console.WriteLine()
+ Console.WriteLine("Mean for all tasks: {0:N2} (N={1:N0})",
+ (total * 1.0) / n, n)
+ Catch e As AggregateException
+ For Each ie In e.InnerExceptions
+ Console.WriteLine("{0}: {1}", ie.GetType().Name, ie.Message)
+ Next
+ End Try
+ End Sub
+End Module
+' The example displays output like the following:
+' Mean for task 1: 499.04 (N=10,000)
+' Mean for task 2: 500.42 (N=10,000)
+' Mean for task 3: 499.65 (N=10,000)
+' Mean for task 8: 502.59 (N=10,000)
+' Mean for task 5: 502.75 (N=10,000)
+' Mean for task 4: 494.88 (N=10,000)
+' Mean for task 7: 499.22 (N=10,000)
+' Mean for task 10: 496.45 (N=10,000)
+' Mean for task 6: 499.75 (N=10,000)
+' Mean for task 9: 502.79 (N=10,000)
+'
+' Mean for all tasks: 499.75 (N=100,000)
+'
diff --git a/snippets/visualbasic/System.Threading/Monitor/Overview/source.vb b/snippets/visualbasic/System.Threading/Monitor/Overview/source.vb
new file mode 100644
index 00000000000..9c553540239
--- /dev/null
+++ b/snippets/visualbasic/System.Threading/Monitor/Overview/source.vb
@@ -0,0 +1,110 @@
+'
+Imports System.Threading
+
+Friend Class SyncResource
+ ' Use a monitor to enforce synchronization.
+ Public Sub Access()
+ SyncLock Me
+ Console.WriteLine("Starting synchronized resource access on thread #{0}",
+ Thread.CurrentThread.ManagedThreadId)
+ If Thread.CurrentThread.ManagedThreadId Mod 2 = 0 Then
+ Thread.Sleep(2000)
+ End If
+ Thread.Sleep(200)
+ Console.WriteLine("Stopping synchronized resource access on thread #{0}",
+ Thread.CurrentThread.ManagedThreadId)
+ End SyncLock
+ End Sub
+End Class
+
+Friend Class UnSyncResource
+ ' Do not enforce synchronization.
+ Public Sub Access()
+ Console.WriteLine("Starting unsynchronized resource access on Thread #{0}",
+ Thread.CurrentThread.ManagedThreadId)
+ If Thread.CurrentThread.ManagedThreadId Mod 2 = 0 Then
+ Thread.Sleep(2000)
+ End If
+ Thread.Sleep(200)
+ Console.WriteLine("Stopping unsynchronized resource access on thread #{0}",
+ Thread.CurrentThread.ManagedThreadId)
+ End Sub
+End Class
+
+Public Module App
+ Private numOps As Integer
+ Private opsAreDone As New AutoResetEvent(False)
+ Private SyncRes As New SyncResource()
+ Private UnSyncRes As New UnSyncResource()
+
+ Public Sub Main()
+ ' Set the number of synchronized calls.
+ numOps = 5
+ For ctr As Integer = 0 To 4
+ ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf SyncUpdateResource))
+ Next
+ ' Wait until this WaitHandle is signaled.
+ opsAreDone.WaitOne()
+ Console.WriteLine(vbTab + Environment.NewLine + "All synchronized operations have completed.")
+ Console.WriteLine()
+
+ numOps = 5
+ ' Reset the count for unsynchronized calls.
+ For ctr As Integer = 0 To 4
+ ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf UnSyncUpdateResource))
+ Next
+
+ ' Wait until this WaitHandle is signaled.
+ opsAreDone.WaitOne()
+ Console.WriteLine(vbTab + Environment.NewLine + "All unsynchronized thread operations have completed.")
+ End Sub
+
+ Sub SyncUpdateResource()
+ ' Call the internal synchronized method.
+ SyncRes.Access()
+
+ ' Ensure that only one thread can decrement the counter at a time.
+ If Interlocked.Decrement(numOps) = 0 Then
+ ' Announce to Main that in fact all thread calls are done.
+ opsAreDone.Set()
+ End If
+ End Sub
+
+ Sub UnSyncUpdateResource()
+ ' Call the unsynchronized method.
+ UnSyncRes.Access()
+
+ ' Ensure that only one thread can decrement the counter at a time.
+ If Interlocked.Decrement(numOps) = 0 Then
+ ' Announce to Main that in fact all thread calls are done.
+ opsAreDone.Set()
+ End If
+ End Sub
+End Module
+' The example displays output like the following:
+' Starting synchronized resource access on thread #6
+' Stopping synchronized resource access on thread #6
+' Starting synchronized resource access on thread #7
+' Stopping synchronized resource access on thread #7
+' Starting synchronized resource access on thread #3
+' Stopping synchronized resource access on thread #3
+' Starting synchronized resource access on thread #4
+' Stopping synchronized resource access on thread #4
+' Starting synchronized resource access on thread #5
+' Stopping synchronized resource access on thread #5
+'
+' All synchronized operations have completed.
+'
+' Starting unsynchronized resource access on Thread #7
+' Starting unsynchronized resource access on Thread #9
+' Starting unsynchronized resource access on Thread #10
+' Starting unsynchronized resource access on Thread #6
+' Starting unsynchronized resource access on Thread #3
+' Stopping unsynchronized resource access on thread #7
+' Stopping unsynchronized resource access on thread #9
+' Stopping unsynchronized resource access on thread #3
+' Stopping unsynchronized resource access on thread #10
+' Stopping unsynchronized resource access on thread #6
+'
+' All unsynchronized thread operations have completed.
+'
diff --git a/snippets/visualbasic/System.Threading/ReaderWriterLockSlim/Overview/Project.vbproj b/snippets/visualbasic/System.Threading/ReaderWriterLockSlim/Overview/Project.vbproj
new file mode 100644
index 00000000000..874c98f3477
--- /dev/null
+++ b/snippets/visualbasic/System.Threading/ReaderWriterLockSlim/Overview/Project.vbproj
@@ -0,0 +1,8 @@
+
+
+
+ Library
+ net10.0
+
+
+
diff --git a/snippets/visualbasic/System.Threading/ReaderWriterLockSlim/Overview/classexample1.vb b/snippets/visualbasic/System.Threading/ReaderWriterLockSlim/Overview/classexample1.vb
new file mode 100644
index 00000000000..d7943bc2c4c
--- /dev/null
+++ b/snippets/visualbasic/System.Threading/ReaderWriterLockSlim/Overview/classexample1.vb
@@ -0,0 +1,211 @@
+' Visual Basic .NET Document
+Option Strict On
+
+'
+Imports System.Collections.Generic
+Imports System.Threading
+Imports System.Threading.Tasks
+
+'
+
+'
+Public Class SynchronizedCache
+ Private cacheLock As New ReaderWriterLockSlim()
+ Private innerCache As New Dictionary(Of Integer, String)
+
+ Public ReadOnly Property Count As Integer
+ Get
+ Return innerCache.Count
+ End Get
+ End Property
+
+ Public Function Read(ByVal key As Integer) As String
+ cacheLock.EnterReadLock()
+ Try
+ Return innerCache(key)
+ Finally
+ cacheLock.ExitReadLock()
+ End Try
+ End Function
+
+ Public Sub Add(ByVal key As Integer, ByVal value As String)
+ cacheLock.EnterWriteLock()
+ Try
+ innerCache.Add(key, value)
+ Finally
+ cacheLock.ExitWriteLock()
+ End Try
+ End Sub
+
+ Public Function AddWithTimeout(ByVal key As Integer, ByVal value As String, _
+ ByVal timeout As Integer) As Boolean
+ If cacheLock.TryEnterWriteLock(timeout) Then
+ Try
+ innerCache.Add(key, value)
+ Finally
+ cacheLock.ExitWriteLock()
+ End Try
+ Return True
+ Else
+ Return False
+ End If
+ End Function
+
+ Public Function AddOrUpdate(ByVal key As Integer, _
+ ByVal value As String) As AddOrUpdateStatus
+ cacheLock.EnterUpgradeableReadLock()
+ Try
+ Dim result As String = Nothing
+ If innerCache.TryGetValue(key, result) Then
+ If result = value Then
+ Return AddOrUpdateStatus.Unchanged
+ Else
+ cacheLock.EnterWriteLock()
+ Try
+ innerCache.Item(key) = value
+ Finally
+ cacheLock.ExitWriteLock()
+ End Try
+ Return AddOrUpdateStatus.Updated
+ End If
+ Else
+ cacheLock.EnterWriteLock()
+ Try
+ innerCache.Add(key, value)
+ Finally
+ cacheLock.ExitWriteLock()
+ End Try
+ Return AddOrUpdateStatus.Added
+ End If
+ Finally
+ cacheLock.ExitUpgradeableReadLock()
+ End Try
+ End Function
+
+ Public Sub Delete(ByVal key As Integer)
+ cacheLock.EnterWriteLock()
+ Try
+ innerCache.Remove(key)
+ Finally
+ cacheLock.ExitWriteLock()
+ End Try
+ End Sub
+
+ Public Enum AddOrUpdateStatus
+ Added
+ Updated
+ Unchanged
+ End Enum
+
+ Protected Overrides Sub Finalize()
+ If cacheLock IsNot Nothing Then cacheLock.Dispose()
+ End Sub
+End Class
+'
+
+'
+Public Module Example
+ Public Sub Main()
+ Dim sc As New SynchronizedCache()
+ Dim tasks As New List(Of Task)
+ Dim itemsWritten As Integer
+
+ ' Execute a writer.
+ tasks.Add(Task.Run( Sub()
+ Dim vegetables() As String = { "broccoli", "cauliflower",
+ "carrot", "sorrel", "baby turnip",
+ "beet", "brussel sprout",
+ "cabbage", "plantain",
+ "spinach", "grape leaves",
+ "lime leaves", "corn",
+ "radish", "cucumber",
+ "raddichio", "lima beans" }
+ For ctr As Integer = 1 to vegetables.Length
+ sc.Add(ctr, vegetables(ctr - 1))
+ Next
+ itemsWritten = vegetables.Length
+ Console.WriteLine("Task {0} wrote {1} items{2}",
+ Task.CurrentId, itemsWritten, vbCrLf)
+ End Sub))
+ ' Execute two readers, one to read from first to last and the second from last to first.
+ For ctr As Integer = 0 To 1
+ Dim flag As Integer = ctr
+ tasks.Add(Task.Run( Sub()
+ Dim start, last, stp As Integer
+ Dim items As Integer
+ Do
+ Dim output As String = String.Empty
+ items = sc.Count
+ If flag = 0 Then
+ start = 1 : stp = 1 : last = items
+ Else
+ start = items : stp = -1 : last = 1
+ End If
+ For index As Integer = start To last Step stp
+ output += String.Format("[{0}] ", sc.Read(index))
+ Next
+ Console.WriteLine("Task {0} read {1} items: {2}{3}",
+ Task.CurrentId, items, output,
+ vbCrLf)
+ Loop While items < itemsWritten Or itemsWritten = 0
+ End Sub))
+ Next
+ ' Execute a read/update task.
+ tasks.Add(Task.Run( Sub()
+ For ctr As Integer = 1 To sc.Count
+ Dim value As String = sc.Read(ctr)
+ If value = "cucumber" Then
+ If sc.AddOrUpdate(ctr, "green bean") <> SynchronizedCache.AddOrUpdateStatus.Unchanged Then
+ Console.WriteLine("Changed 'cucumber' to 'green bean'")
+ End If
+ End If
+ Next
+ End Sub ))
+
+ ' Wait for all three tasks to complete.
+ Task.WaitAll(tasks.ToArray())
+
+ ' Display the final contents of the cache.
+ Console.WriteLine()
+ Console.WriteLine("Values in synchronized cache: ")
+ For ctr As Integer = 1 To sc.Count
+ Console.WriteLine(" {0}: {1}", ctr, sc.Read(ctr))
+ Next
+ End Sub
+End Module
+' The example displays output like the following:
+' Task 1 read 0 items:
+'
+' Task 3 wrote 17 items
+'
+' Task 1 read 17 items: [broccoli] [cauliflower] [carrot] [sorrel] [baby turnip] [
+' beet] [brussel sprout] [cabbage] [plantain] [spinach] [grape leaves] [lime leave
+' s] [corn] [radish] [cucumber] [raddichio] [lima beans]
+'
+' Task 2 read 0 items:
+'
+' Task 2 read 17 items: [lima beans] [raddichio] [cucumber] [radish] [corn] [lime
+' leaves] [grape leaves] [spinach] [plantain] [cabbage] [brussel sprout] [beet] [b
+' aby turnip] [sorrel] [carrot] [cauliflower] [broccoli]
+'
+' Changed 'cucumber' to 'green bean'
+'
+' Values in synchronized cache:
+' 1: broccoli
+' 2: cauliflower
+' 3: carrot
+' 4: sorrel
+' 5: baby turnip
+' 6: beet
+' 7: brussel sprout
+' 8: cabbage
+' 9: plantain
+' 10: spinach
+' 11: grape leaves
+' 12: lime leaves
+' 13: corn
+' 14: radish
+' 15: green bean
+' 16: raddichio
+' 17: lima beans
+'
diff --git a/snippets/visualbasic/System.Threading/Thread/Overview/BackgroundEx1.vb b/snippets/visualbasic/System.Threading/Thread/Overview/BackgroundEx1.vb
new file mode 100644
index 00000000000..f3020b9ae83
--- /dev/null
+++ b/snippets/visualbasic/System.Threading/Thread/Overview/BackgroundEx1.vb
@@ -0,0 +1,39 @@
+' Visual Basic .NET Document
+Option Strict On
+
+'
+Imports System.Diagnostics
+Imports System.Threading
+
+Module Example1
+ Public Sub Main()
+ Dim th As New Thread(AddressOf ExecuteInForeground)
+ th.IsBackground = True
+ th.Start()
+ Thread.Sleep(1000)
+ Console.WriteLine("Main thread ({0}) exiting...", Thread.CurrentThread.ManagedThreadId)
+ End Sub
+
+ Private Sub ExecuteInForeground()
+ Dim start As DateTime = DateTime.Now
+ Dim sw As Stopwatch = Stopwatch.StartNew()
+ Console.WriteLine("Thread {0}: {1}, Priority {2}",
+ Thread.CurrentThread.ManagedThreadId,
+ Thread.CurrentThread.ThreadState,
+ Thread.CurrentThread.Priority)
+ Do
+ Console.WriteLine("Thread {0}: Elapsed {1:N2} seconds",
+ Thread.CurrentThread.ManagedThreadId,
+ sw.ElapsedMilliseconds / 1000)
+ Thread.Sleep(500)
+ Loop While sw.ElapsedMilliseconds <= 5000
+ sw.Stop()
+ End Sub
+End Module
+' The example displays output like the following:
+' Thread 3: Background, Priority Normal
+' Thread 3: Elapsed 0.00 seconds
+' Thread 3: Elapsed 0.51 seconds
+' Main thread (1) exiting...
+'
+
diff --git a/snippets/visualbasic/System.Threading/Thread/Overview/Instance1.vb b/snippets/visualbasic/System.Threading/Thread/Overview/Instance1.vb
new file mode 100644
index 00000000000..8f6d5ae3a6e
--- /dev/null
+++ b/snippets/visualbasic/System.Threading/Thread/Overview/Instance1.vb
@@ -0,0 +1,63 @@
+' Visual Basic .NET Document
+Option Strict On
+
+'
+Imports System.Threading
+
+Module Example2
+ Private lock As New Object()
+
+ Public Sub Main()
+ ThreadPool.QueueUserWorkItem(AddressOf ShowThreadInformation)
+ Dim th1 As New Thread(AddressOf ShowThreadInformation)
+ th1.Start()
+ Dim th2 As New Thread(AddressOf ShowThreadInformation)
+ th2.IsBackground = True
+ th2.Start()
+ Thread.Sleep(500)
+ ShowThreadInformation(Nothing)
+ End Sub
+
+ Private Sub ShowThreadInformation(state As Object)
+ SyncLock lock
+ Dim th As Thread = Thread.CurrentThread
+ Console.WriteLine("Managed thread #{0}: ", th.ManagedThreadId)
+ Console.WriteLine(" Background thread: {0}", th.IsBackground)
+ Console.WriteLine(" Thread pool thread: {0}", th.IsThreadPoolThread)
+ Console.WriteLine(" Priority: {0}", th.Priority)
+ Console.WriteLine(" Culture: {0}", th.CurrentCulture.Name)
+ Console.WriteLine(" UI culture: {0}", th.CurrentUICulture.Name)
+ Console.WriteLine()
+ End SyncLock
+ End Sub
+End Module
+' The example displays output like the following:
+' ' Managed thread #6:
+' Background thread: True
+' Thread pool thread: False
+' Priority: Normal
+' Culture: en-US
+' UI culture: en-US
+'
+' Managed thread #3:
+' Background thread: True
+' Thread pool thread: True
+' Priority: Normal
+' Culture: en-US
+' UI culture: en-US
+'
+' Managed thread #4:
+' Background thread: False
+' Thread pool thread: False
+' Priority: Normal
+' Culture: en-US
+' UI culture: en-US
+'
+' Managed thread #1:
+' Background thread: False
+' Thread pool thread: False
+' Priority: Normal
+' Culture: en-US
+' UI culture: en-US
+'
+
diff --git a/snippets/visualbasic/System.Threading/Thread/Overview/Project.vbproj b/snippets/visualbasic/System.Threading/Thread/Overview/Project.vbproj
new file mode 100644
index 00000000000..874c98f3477
--- /dev/null
+++ b/snippets/visualbasic/System.Threading/Thread/Overview/Project.vbproj
@@ -0,0 +1,8 @@
+
+
+
+ Library
+ net10.0
+
+
+
diff --git a/snippets/visualbasic/System.Threading/Thread/Overview/ThreadStart1.vb b/snippets/visualbasic/System.Threading/Thread/Overview/ThreadStart1.vb
new file mode 100644
index 00000000000..4ddc5ac250a
--- /dev/null
+++ b/snippets/visualbasic/System.Threading/Thread/Overview/ThreadStart1.vb
@@ -0,0 +1,46 @@
+' Visual Basic .NET Document
+Option Strict On
+
+'
+Imports System.Diagnostics
+Imports System.Threading
+
+Module Example3
+ Public Sub Main()
+ Dim th As New Thread(AddressOf ExecuteInForeground)
+ th.Start()
+ Thread.Sleep(1000)
+ Console.WriteLine("Main thread ({0}) exiting...", Thread.CurrentThread.ManagedThreadId)
+ End Sub
+
+ Private Sub ExecuteInForeground()
+ Dim start As DateTime = DateTime.Now
+ Dim sw As Stopwatch = Stopwatch.StartNew()
+ Console.WriteLine("Thread {0}: {1}, Priority {2}",
+ Thread.CurrentThread.ManagedThreadId,
+ Thread.CurrentThread.ThreadState,
+ Thread.CurrentThread.Priority)
+ Do
+ Console.WriteLine("Thread {0}: Elapsed {1:N2} seconds",
+ Thread.CurrentThread.ManagedThreadId,
+ sw.ElapsedMilliseconds / 1000)
+ Thread.Sleep(500)
+ Loop While sw.ElapsedMilliseconds <= 5000
+ sw.Stop()
+ End Sub
+End Module
+' The example displays output like the following:
+' Thread 3: Running, Priority Normal
+' Thread 3: Elapsed 0.00 seconds
+' Thread 3: Elapsed 0.51 seconds
+' Main thread (1) exiting...
+' Thread 3: Elapsed 1.02 seconds
+' Thread 3: Elapsed 1.53 seconds
+' Thread 3: Elapsed 2.05 seconds
+' Thread 3: Elapsed 2.55 seconds
+' Thread 3: Elapsed 3.07 seconds
+' Thread 3: Elapsed 3.57 seconds
+' Thread 3: Elapsed 4.07 seconds
+' Thread 3: Elapsed 4.58 seconds
+'
+
diff --git a/snippets/visualbasic/System.Threading/Thread/Overview/ThreadStart2.vb b/snippets/visualbasic/System.Threading/Thread/Overview/ThreadStart2.vb
new file mode 100644
index 00000000000..8bad0fa3512
--- /dev/null
+++ b/snippets/visualbasic/System.Threading/Thread/Overview/ThreadStart2.vb
@@ -0,0 +1,51 @@
+' Visual Basic .NET Document
+Option Strict On
+
+'
+Imports System.Diagnostics
+Imports System.Threading
+
+Module Example4
+ Public Sub Main()
+ Dim th As New Thread(AddressOf ExecuteInForeground)
+ th.Start(4500)
+ Thread.Sleep(1000)
+ Console.WriteLine("Main thread ({0}) exiting...", Thread.CurrentThread.ManagedThreadId)
+ End Sub
+
+ Private Sub ExecuteInForeground(obj As Object)
+ Dim interval As Integer
+ If IsNumeric(obj) Then
+ interval = CInt(obj)
+ Else
+ interval = 5000
+ End If
+ Dim start As DateTime = DateTime.Now
+ Dim sw As Stopwatch = Stopwatch.StartNew()
+ Console.WriteLine("Thread {0}: {1}, Priority {2}",
+ Thread.CurrentThread.ManagedThreadId,
+ Thread.CurrentThread.ThreadState,
+ Thread.CurrentThread.Priority)
+ Do
+ Console.WriteLine("Thread {0}: Elapsed {1:N2} seconds",
+ Thread.CurrentThread.ManagedThreadId,
+ sw.ElapsedMilliseconds / 1000)
+ Thread.Sleep(500)
+ Loop While sw.ElapsedMilliseconds <= interval
+ sw.Stop()
+ End Sub
+End Module
+' The example displays output like the following:
+' Thread 3: Running, Priority Normal
+' Thread 3: Elapsed 0.00 seconds
+' Thread 3: Elapsed 0.52 seconds
+' Main thread (1) exiting...
+' Thread 3: Elapsed 1.03 seconds
+' Thread 3: Elapsed 1.55 seconds
+' Thread 3: Elapsed 2.06 seconds
+' Thread 3: Elapsed 2.58 seconds
+' Thread 3: Elapsed 3.09 seconds
+' Thread 3: Elapsed 3.61 seconds
+' Thread 3: Elapsed 4.12 seconds
+'
+
diff --git a/snippets/visualbasic/System.Threading/Thread/Overview/source.vb b/snippets/visualbasic/System.Threading/Thread/Overview/source.vb
new file mode 100644
index 00000000000..7f9837184ec
--- /dev/null
+++ b/snippets/visualbasic/System.Threading/Thread/Overview/source.vb
@@ -0,0 +1,45 @@
+'
+Imports System.Threading
+
+' Simple threading scenario: Start a Shared method running
+' on a second thread.
+Public Class ThreadExample
+ ' The ThreadProc method is called when the thread starts.
+ ' It loops ten times, writing to the console and yielding
+ ' the rest of its time slice each time, and then ends.
+ Public Shared Sub ThreadProc()
+ Dim i As Integer
+ For i = 0 To 9
+ Console.WriteLine("ThreadProc: {0}", i)
+ ' Yield the rest of the time slice.
+ Thread.Sleep(0)
+ Next
+ End Sub
+
+ Public Shared Sub Main()
+ Console.WriteLine("Main thread: Start a second thread.")
+ ' The constructor for the Thread class requires a ThreadStart
+ ' delegate. The Visual Basic AddressOf operator creates this
+ ' delegate for you.
+ Dim t As New Thread(AddressOf ThreadProc)
+
+ ' Start ThreadProc. Note that on a uniprocessor, the new
+ ' thread does not get any processor time until the main thread
+ ' is preempted or yields. Uncomment the Thread.Sleep that
+ ' follows t.Start() to see the difference.
+ t.Start()
+ 'Thread.Sleep(0)
+
+ Dim i As Integer
+ For i = 1 To 4
+ Console.WriteLine("Main thread: Do some work.")
+ Thread.Sleep(0)
+ Next
+
+ Console.WriteLine("Main thread: Call Join(), to wait until ThreadProc ends.")
+ t.Join()
+ Console.WriteLine("Main thread: ThreadProc.Join has returned. Press Enter to end program.")
+ Console.ReadLine()
+ End Sub
+End Class
+'
diff --git a/xml/System.Text.RegularExpressions/Regex.xml b/xml/System.Text.RegularExpressions/Regex.xml
index 89292b8a774..2c835398007 100644
--- a/xml/System.Text.RegularExpressions/Regex.xml
+++ b/xml/System.Text.RegularExpressions/Regex.xml
@@ -3531,11 +3531,7 @@
specified starting position in the string.
An object that contains information about the match.
-
- For more information about , see
-
- Supplemental API remarks for Regex.Match.
-
+ To be added.Regular Expression Language - Quick Reference
diff --git a/xml/System.Text/Encoding.xml b/xml/System.Text/Encoding.xml
index 9c342d046fe..276eb22f5af 100644
--- a/xml/System.Text/Encoding.xml
+++ b/xml/System.Text/Encoding.xml
@@ -75,7 +75,211 @@
Represents a character encoding.
- For more information about this API, see Supplemental API remarks for Encoding.
+
+ class represents a character encoding.
+
+Encoding is the process of transforming a set of Unicode characters into a sequence of bytes. In contrast, decoding is the process of transforming a sequence of encoded bytes into a set of Unicode characters. For information about the Unicode Transformation Formats (UTFs) and other encodings supported by , see [Character Encoding in .NET](/dotnet/standard/base-types/character-encoding).
+
+ is intended to operate on Unicode characters instead of arbitrary binary data, such as byte arrays. If you must encode arbitrary binary data into text, you should use a protocol such as uuencode, which is implemented by methods such as .
+
+.NET provides the following implementations of the class to support current Unicode encodings and other encodings:
+
+- encodes Unicode characters as single 7-bit ASCII characters. This encoding only supports character values between U+0000 and U+007F. Code page 20127. Also available through the property.
+
+- encodes Unicode characters using the UTF-7 encoding. This encoding supports all Unicode character values. Code page 65000. Also available through the property.
+
+- encodes Unicode characters using the UTF-8 encoding. This encoding supports all Unicode character values. Code page 65001. Also available through the property.
+
+- encodes Unicode characters using the UTF-16 encoding. Both little endian and big endian byte orders are supported. Also available through the property and the property.
+
+- encodes Unicode characters using the UTF-32 encoding. Both little endian (code page 12000) and big endian (code page 12001) byte orders are supported. Also available through the property.
+
+The class is primarily intended to convert between different encodings and Unicode. Often one of the derived Unicode classes is the correct choice for your app.
+
+Use the method to obtain other encodings, and call the method to get a list of all encodings.
+
+## List of encodings
+
+The following table lists the encodings supported by .NET. It lists each encoding's code page number and the values of the encoding's and properties. A check mark in the **.NET Framework support**, **.NET Core support**, or **.NET 5 and later support** column indicates that the code page is natively supported by that .NET implementation, regardless of the underlying platform. For .NET Framework, the availability of other encodings listed in the table depends on the operating system. For .NET Core and .NET 5 and later versions, other encodings are available by using the class or by deriving from the class.
+
+> [!NOTE]
+> Code pages whose property corresponds to an international standard do not necessarily comply in full with that standard.
+
+|Code page|Name|Display name|.NET Framework support| .NET Core support | .NET 5 and later support |
+|---------|----|------------|----------------------|-------------------|----------------------------|
+|37|IBM037|IBM EBCDIC (US-Canada)||||
+|437|IBM437|OEM United States||||
+|500|IBM500|IBM EBCDIC (International)||||
+|708|ASMO-708|Arabic (ASMO 708)||||
+|720|DOS-720|Arabic (DOS)||||
+|737|ibm737|Greek (DOS)||||
+|775|ibm775|Baltic (DOS)||||
+|850|ibm850|Western European (DOS)||||
+|852|ibm852|Central European (DOS)||||
+|855|IBM855|OEM Cyrillic||||
+|857|ibm857|Turkish (DOS)||||
+|858|IBM00858|OEM Multilingual Latin I||||
+|860|IBM860|Portuguese (DOS)||||
+|861|ibm861|Icelandic (DOS)||||
+|862|DOS-862|Hebrew (DOS)||||
+|863|IBM863|French Canadian (DOS)||||
+|864|IBM864|Arabic (864)||||
+|865|IBM865|Nordic (DOS)||||
+|866|cp866|Cyrillic (DOS)||||
+|869|ibm869|Greek, Modern (DOS)||||
+|870|IBM870|IBM EBCDIC (Multilingual Latin-2)||||
+|874|windows-874|Thai (Windows)||||
+|875|cp875|IBM EBCDIC (Greek Modern)||||
+|932|shift_jis|Japanese (Shift-JIS)||||
+|936|gb2312|Chinese Simplified (GB2312)|✓|||
+|949|ks_c_5601-1987|Korean||||
+|950|big5|Chinese Traditional (Big5)||||
+|1026|IBM1026|IBM EBCDIC (Turkish Latin-5)||||
+|1047|IBM01047|IBM Latin-1||||
+|1140|IBM01140|IBM EBCDIC (US-Canada-Euro)||||
+|1141|IBM01141|IBM EBCDIC (Germany-Euro)||||
+|1142|IBM01142|IBM EBCDIC (Denmark-Norway-Euro)||||
+|1143|IBM01143|IBM EBCDIC (Finland-Sweden-Euro)||||
+|1144|IBM01144|IBM EBCDIC (Italy-Euro)||||
+|1145|IBM01145|IBM EBCDIC (Spain-Euro)||||
+|1146|IBM01146|IBM EBCDIC (UK-Euro)||||
+|1147|IBM01147|IBM EBCDIC (France-Euro)||||
+|1148|IBM01148|IBM EBCDIC (International-Euro)||||
+|1149|IBM01149|IBM EBCDIC (Icelandic-Euro)||||
+|1200|utf-16|Unicode|✓|✓|✓|
+|1201|unicodeFFFE|Unicode (Big endian)|✓|✓|✓|
+|1250|windows-1250|Central European (Windows)||||
+|1251|windows-1251|Cyrillic (Windows)||||
+|1252|Windows-1252|Western European (Windows)|✓|||
+|1253|windows-1253|Greek (Windows)||||
+|1254|windows-1254|Turkish (Windows)||||
+|1255|windows-1255|Hebrew (Windows)||||
+|1256|windows-1256|Arabic (Windows)||||
+|1257|windows-1257|Baltic (Windows)||||
+|1258|windows-1258|Vietnamese (Windows)||||
+|1361|Johab|Korean (Johab)||||
+|10000|macintosh|Western European (Mac)||||
+|10001|x-mac-japanese|Japanese (Mac)||||
+|10002|x-mac-chinesetrad|Chinese Traditional (Mac)||||
+|10003|x-mac-korean|Korean (Mac)|✓|||
+|10004|x-mac-arabic|Arabic (Mac)||||
+|10005|x-mac-hebrew|Hebrew (Mac)||||
+|10006|x-mac-greek|Greek (Mac)||||
+|10007|x-mac-cyrillic|Cyrillic (Mac)||||
+|10008|x-mac-chinesesimp|Chinese Simplified (Mac)|✓|||
+|10010|x-mac-romanian|Romanian (Mac)||||
+|10017|x-mac-ukrainian|Ukrainian (Mac)||||
+|10021|x-mac-thai|Thai (Mac)||||
+|10029|x-mac-ce|Central European (Mac)||||
+|10079|x-mac-icelandic|Icelandic (Mac)||||
+|10081|x-mac-turkish|Turkish (Mac)||||
+|10082|x-mac-croatian|Croatian (Mac)||||
+|12000|utf-32|Unicode (UTF-32)|✓|✓|✓|
+|12001|utf-32BE|Unicode (UTF-32 Big endian)|✓|✓|✓|
+|20000|x-Chinese-CNS|Chinese Traditional (CNS)||||
+|20001|x-cp20001|TCA Taiwan||||
+|20002|x-Chinese-Eten|Chinese Traditional (Eten)||||
+|20003|x-cp20003|IBM5550 Taiwan||||
+|20004|x-cp20004|TeleText Taiwan||||
+|20005|x-cp20005|Wang Taiwan||||
+|20105|x-IA5|Western European (IA5)||||
+|20106|x-IA5-German|German (IA5)||||
+|20107|x-IA5-Swedish|Swedish (IA5)||||
+|20108|x-IA5-Norwegian|Norwegian (IA5)||||
+|20127|us-ascii|US-ASCII|✓|✓|✓|
+|20261|x-cp20261|T.61||||
+|20269|x-cp20269|ISO-6937||||
+|20273|IBM273|IBM EBCDIC (Germany)||||
+|20277|IBM277|IBM EBCDIC (Denmark-Norway)||||
+|20278|IBM278|IBM EBCDIC (Finland-Sweden)||||
+|20280|IBM280|IBM EBCDIC (Italy)||||
+|20284|IBM284|IBM EBCDIC (Spain)||||
+|20285|IBM285|IBM EBCDIC (UK)||||
+|20290|IBM290|IBM EBCDIC (Japanese katakana)||||
+|20297|IBM297|IBM EBCDIC (France)||||
+|20420|IBM420|IBM EBCDIC (Arabic)||||
+|20423|IBM423|IBM EBCDIC (Greek)||||
+|20424|IBM424|IBM EBCDIC (Hebrew)||||
+|20833|x-EBCDIC-KoreanExtended|IBM EBCDIC (Korean Extended)||||
+|20838|IBM-Thai|IBM EBCDIC (Thai)||||
+|20866|koi8-r|Cyrillic (KOI8-R)||||
+|20871|IBM871|IBM EBCDIC (Icelandic)||||
+|20880|IBM880|IBM EBCDIC (Cyrillic Russian)||||
+|20905|IBM905|IBM EBCDIC (Turkish)||||
+|20924|IBM00924|IBM Latin-1||||
+|20932|EUC-JP|Japanese (JIS 0208-1990 and 0212-1990)||||
+|20936|x-cp20936|Chinese Simplified (GB2312-80)|✓|||
+|20949|x-cp20949|Korean Wansung|✓|||
+|21025|cp1025|IBM EBCDIC (Cyrillic Serbian-Bulgarian)||||
+|21866|koi8-u|Cyrillic (KOI8-U)||||
+|28591|iso-8859-1|Western European (ISO)|✓|✓|✓|
+|28592|iso-8859-2|Central European (ISO)||||
+|28593|iso-8859-3|Latin 3 (ISO)||||
+|28594|iso-8859-4|Baltic (ISO)||||
+|28595|iso-8859-5|Cyrillic (ISO)||||
+|28596|iso-8859-6|Arabic (ISO)||||
+|28597|iso-8859-7|Greek (ISO)||||
+|28598|iso-8859-8|Hebrew (ISO-Visual)|✓|||
+|28599|iso-8859-9|Turkish (ISO)||||
+|28603|iso-8859-13|Estonian (ISO)||||
+|28605|iso-8859-15|Latin 9 (ISO)||||
+|29001|x-Europa|Europa||||
+|38598|iso-8859-8-i|Hebrew (ISO-Logical)|✓|||
+|50220|iso-2022-jp|Japanese (JIS)|✓|||
+|50221|csISO2022JP|Japanese (JIS-Allow 1 byte Kana)|✓|||
+|50222|iso-2022-jp|Japanese (JIS-Allow 1 byte Kana - SO/SI)|✓|||
+|50225|iso-2022-kr|Korean (ISO)|✓|||
+|50227|x-cp50227|Chinese Simplified (ISO-2022)|✓|||
+|51932|euc-jp|Japanese (EUC)|✓|||
+|51936|EUC-CN|Chinese Simplified (EUC)|✓|||
+|51949|euc-kr|Korean (EUC)|✓|||
+|52936|hz-gb-2312|Chinese Simplified (HZ)|✓|||
+|54936|GB18030|Chinese Simplified (GB18030)|✓|||
+|57002|x-iscii-de|ISCII Devanagari|✓|||
+|57003|x-iscii-be|ISCII Bengali|✓|||
+|57004|x-iscii-ta|ISCII Tamil|✓|||
+|57005|x-iscii-te|ISCII Telugu|✓|||
+|57006|x-iscii-as|ISCII Assamese|✓|||
+|57007|x-iscii-or|ISCII Oriya|✓|||
+|57008|x-iscii-ka|ISCII Kannada|✓|||
+|57009|x-iscii-ma|ISCII Malayalam|✓|||
+|57010|x-iscii-gu|ISCII Gujarati|✓|||
+|57011|x-iscii-pa|ISCII Punjabi|✓|||
+|65000|utf-7|Unicode (UTF-7)|✓|✓||
+|65001|utf-8|Unicode (UTF-8)|✓|✓|✓|
+
+The following example calls the and methods to get the Greek (Windows) code page encoding. It compares the objects returned by the method calls to show that they are equal, and then maps displays the Unicode code point and the corresponding code page value for each character in the Greek alphabet.
+
+:::code language="csharp" source="~/snippets/csharp/System.Text/Encoding/Overview/getencoding1.cs" id="Snippet1":::
+:::code language="vb" source="~/snippets/visualbasic/System.Text/Encoding/Overview/getencoding1.vb" id="Snippet1":::
+
+If the data to be converted is available only in sequential blocks (such as data read from a stream) or if the amount of data is so large that it needs to be divided into smaller blocks, you should use the or the provided by the method or the method, respectively, of a derived class.
+
+The UTF-16 and the UTF-32 encoders can use the big endian byte order (most significant byte first) or the little endian byte order (least significant byte first). For example, the Latin Capital Letter A (U+0041) is serialized as follows (in hexadecimal):
+
+- UTF-16 big endian byte order: 00 41
+- UTF-16 little endian byte order: 41 00
+- UTF-32 big endian byte order: 00 00 00 41
+- UTF-32 little endian byte order: 41 00 00 00
+
+It is generally more efficient to store Unicode characters using the native byte order. For example, it is better to use the little endian byte order on little endian platforms, such as Intel computers.
+
+The method retrieves an array of bytes that includes the byte order mark (BOM). If this byte array is prefixed to an encoded stream, it helps the decoder to identify the encoding format used.
+
+For more information on byte order and the byte order mark, see The Unicode Standard at the [Unicode home page](https://home.unicode.org/).
+
+Note that the encoding classes allow errors to:
+
+- Silently change to a "?" character.
+- Use a "best fit" character.
+- Change to an application-specific behavior through use of the and classes with the U+FFFD Unicode replacement character.
+
+You should throw an exception on any data stream error. An app either uses a "throwonerror" flag when applicable or uses the and classes. Best fit fallback is often not recommended because it can cause data loss or confusion and is slower than simple character replacements. For ANSI encodings, the best fit behavior is the default.
+
+ ]]>
+ object that is returned by this property may not have the appropriate behavior for your app. It uses replacement fallback to replace each string that it cannot encode and each byte that it cannot decode with a question mark ("?") character. Instead, you can call the constructor to instantiate a big endian object whose fallback is either an or a , as the following example illustrates.
+ The object that is returned by this property might not have the appropriate behavior for your app. It uses replacement fallback to replace each string that it cannot encode and each byte that it cannot decode with a question mark ("?") character. Instead, you can call the constructor to instantiate a big endian object whose fallback is either an or a , as the following example illustrates.
:::code language="csharp" source="~/snippets/csharp/System.Text/Encoding/BigEndianUnicode/bigendianunicode1.cs" id="Snippet2":::
:::code language="vb" source="~/snippets/visualbasic/System.Text/Encoding/BigEndianUnicode/bigendianunicode1.vb" id="Snippet2":::
@@ -956,7 +1160,10 @@ The property always returns a or with "utf-8".
-For more information about this API, see Supplemental API remarks for Encoding.Default.
+> [!WARNING]
+> Different computers can use different encodings as the default, and the default encoding can change on a single computer. If you use the encoding to encode and decode data streamed between computers or retrieved at different times on the same computer, it might translate that data incorrectly. In addition, the encoding returned by the property uses best-fit fallback to map unsupported characters to characters supported by the code page. For these reasons, using the default encoding is not recommended. To ensure that encoded bytes are decoded properly, you should use a Unicode encoding, such as or . You could also use a higher-level protocol to ensure that the same format is used for encoding and decoding.
+
+The property always returns the . UTF-8 is supported on all the operating systems (Windows, Linux, and macOS) on which .NET apps run.
]]>
diff --git a/xml/System.Text/Rune.xml b/xml/System.Text/Rune.xml
index e748b542c16..01e262d58dc 100644
--- a/xml/System.Text/Rune.xml
+++ b/xml/System.Text/Rune.xml
@@ -71,7 +71,199 @@
Represents a Unicode scalar value ([ U+0000..U+D7FF ], inclusive; or [ U+E000..U+10FFFF ], inclusive).
- For more information about this API, see Supplemental API remarks for Rune.
+
+ instance represents a Unicode scalar value, which means any code point excluding the surrogate range (U+D800..U+DFFF). The type's constructors and conversion operators validate the input, so consumers can call the APIs assuming that the underlying instance is well-formed.
+
+If you aren't familiar with the terms Unicode scalar value, code point, surrogate range, and well-formed, see [Introduction to character encoding in .NET](/dotnet/standard/base-types/character-encoding-introduction).
+
+## When to use the Rune type
+
+Consider using the `Rune` type if your code:
+
+* Calls APIs that require Unicode scalar values
+* Explicitly handles surrogate pairs
+
+### APIs that require Unicode scalar values
+
+If your code iterates through the `char` instances in a `string` or a `ReadOnlySpan`, some of the `char` methods won't work correctly on `char` instances that are in the surrogate range. For example, the following APIs require a scalar value `char` to work correctly:
+
+*
+*
+*
+*
+*
+*
+*
+*
+*
+*
+
+The following example shows code that won't work correctly if any of the `char` instances are surrogate code points:
+
+:::code language="csharp" source="~/snippets/csharp/System.Text/Rune/Overview/CountLettersInString.cs" id="SnippetBadExample":::
+:::code language="fsharp" source="~/snippets/fsharp/System.Text/Rune/Overview/CountLettersInString.fs" id="SnippetBadExample":::
+
+Here's equivalent code that works with a `ReadOnlySpan`:
+
+:::code language="csharp" source="~/snippets/csharp/System.Text/Rune/Overview/CountLettersInSpan.cs" id="SnippetBadExample":::
+
+The preceding code works correctly with some languages such as English:
+
+```csharp
+CountLettersInString("Hello")
+// Returns 5
+```
+
+But it won't work correctly for languages outside the Basic Multilingual Plane, such as Osage:
+
+```csharp
+CountLettersInString("𐓏𐓘𐓻𐓘𐓻𐓟 𐒻𐓟")
+// Returns 0
+```
+
+The reason this method returns incorrect results for Osage text is that the `char` instances for Osage letters are surrogate code points. No single surrogate code point has enough information to determine if it's a letter.
+
+If you change this code to use `Rune` instead of `char`, the method works correctly with code points outside the Basic Multilingual Plane:
+
+:::code language="csharp" source="~/snippets/csharp/System.Text/Rune/Overview/CountLettersInString.cs" id="SnippetGoodExample":::
+:::code language="fsharp" source="~/snippets/fsharp/System.Text/Rune/Overview/CountLettersInString.fs" id="SnippetGoodExample":::
+
+Here's equivalent code that works with a `ReadOnlySpan`:
+
+:::code language="csharp" source="~/snippets/csharp/System.Text/Rune/Overview/CountLettersInSpan.cs" id="SnippetGoodExample":::
+
+The preceding code counts Osage letters correctly:
+
+```csharp
+CountLettersInString("𐓏𐓘𐓻𐓘𐓻𐓟 𐒻𐓟")
+// Returns 8
+```
+
+### Code that explicitly handles surrogate pairs
+
+Consider using the `Rune` type if your code calls APIs that explicitly operate on surrogate code points, such as the following methods:
+
+*
+*
+*
+*
+*
+*
+
+For example, the following method has special logic to deal with surrogate `char` pairs:
+
+:::code language="csharp" source="~/snippets/csharp/System.Text/Rune/Overview/WorkWithSurrogates.cs" id="SnippetUseChar":::
+
+Such code is simpler if it uses `Rune`, as in the following example:
+
+:::code language="csharp" source="~/snippets/csharp/System.Text/Rune/Overview/WorkWithSurrogates.cs" id="SnippetUseRune":::
+
+## When not to use `Rune`
+
+You don't need to use the `Rune` type if your code:
+
+* Looks for exact `char` matches
+* Splits a string on a known char value
+
+Using the `Rune` type may return incorrect results if your code:
+
+* Counts the number of display characters in a `string`
+
+### Look for exact `char` matches
+
+The following code iterates through a `string` looking for specific characters, returning the index of the first match. There's no need to change this code to use `Rune`, as the code is looking for characters that are represented by a single `char`.
+
+:::code language="csharp" source="~/snippets/csharp/System.Text/Rune/Overview/FindFirstLetter.cs" id="SnippetExample":::
+
+### Split a string on a known `char`
+
+It's common to call `string.Split` and use delimiters such as `' '` (space) or `','` (comma), as in the following example:
+
+:::code language="csharp" source="~/snippets/csharp/System.Text/Rune/Overview/SplitStringOnChar.cs" id="SnippetExample":::
+
+There is no need to use `Rune` here, because the code is looking for characters that are represented by a single `char`.
+
+### Count the number of display characters in a `string`
+
+The number of `Rune` instances in a string might not match the number of user-perceivable characters shown when displaying the string.
+
+Since `Rune` instances represent Unicode scalar values, components that follow the [Unicode text segmentation guidelines](https://www.unicode.org/reports/tr29/) can use `Rune` as a building block for counting display characters.
+
+The type can be used to count display characters, but it doesn't count correctly in all scenarios for .NET implementations other than .NET 5+.
+
+For more information, see [Grapheme clusters](https://learn.microsoft.com/dotnet/standard/base-types/character-encoding-introduction#grapheme-clusters).
+
+## How to instantiate a `Rune`
+
+There are several ways to get a `Rune` instance. You can use a constructor to create a `Rune` directly from:
+
+* A code point.
+
+ :::code language="csharp" source="~/snippets/csharp/System.Text/Rune/Overview/InstantiateRunes.cs" id="SnippetCodePoint":::
+
+* A single `char`.
+
+ :::code language="csharp" source="~/snippets/csharp/System.Text/Rune/Overview/InstantiateRunes.cs" id="SnippetChar":::
+
+* A surrogate `char` pair.
+
+ :::code language="csharp" source="~/snippets/csharp/System.Text/Rune/Overview/InstantiateRunes.cs" id="SnippetSurrogate":::
+
+All of the constructors throw an `ArgumentException` if the input doesn't represent a valid Unicode scalar value.
+
+There are methods available for callers who don't want exceptions to be thrown on failure.
+
+`Rune` instances can also be read from existing input sequences. For instance, given a `ReadOnlySpan` that represents UTF-16 data, the method returns the first `Rune` instance at the beginning of the input span. The method operates similarly, accepting a `ReadOnlySpan` parameter that represents UTF-8 data. There are equivalent methods to read from the end of the span instead of the beginning of the span.
+
+## Query properties of a `Rune`
+
+To get the integer code point value of a `Rune` instance, use the property.
+
+:::code language="csharp" source="~/snippets/csharp/System.Text/Rune/Overview/InstantiateRunes.cs" id="SnippetValue":::
+
+Many of the static APIs available on the `char` type are also available on the `Rune` type. For instance, and are equivalents to and methods. The `Rune` methods correctly handle surrogate pairs.
+
+The following example code takes a `ReadOnlySpan` as input and trims from both the start and the end of the span every `Rune` that isn't a letter or a digit.
+
+:::code language="csharp" source="~/snippets/csharp/System.Text/Rune/Overview/TrimNonLettersAndNonDigits.cs" id="SnippetExample":::
+
+There are some API differences between `char` and `Rune`. For example:
+
+* There is no `Rune` equivalent to , since `Rune` instances by definition can never be surrogate code points.
+* The doesn't always return the same result as . It does return the same value as . For more information, see the **Remarks** on .
+
+## Convert a `Rune` to UTF-8 or UTF-16
+
+Since a `Rune` is a Unicode scalar value, it can be converted to UTF-8, UTF-16, or UTF-32 encoding. The `Rune` type has built-in support for conversion to UTF-8 and UTF-16.
+
+The converts a `Rune` instance to `char` instances. To query the number of `char` instances that would result from converting a `Rune` instance to UTF-16, use the property. Similar methods exist for UTF-8 conversion.
+
+The following example converts a `Rune` instance to a `char` array. The code assumes you have a `Rune` instance in the `rune` variable:
+
+:::code language="csharp" source="~/snippets/csharp/System.Text/Rune/Overview/EncodeRune.cs" id="SnippetUtf16CharArray":::
+
+Since a `string` is a sequence of UTF-16 chars, the following example also converts a `Rune` instance to UTF-16:
+
+:::code language="csharp" source="~/snippets/csharp/System.Text/Rune/Overview/EncodeRune.cs" id="SnippetUtf16String":::
+
+The following example converts a `Rune` instance to a `UTF-8` byte array:
+
+:::code language="csharp" source="~/snippets/csharp/System.Text/Rune/Overview/EncodeRune.cs" id="SnippetUtf8ByteArray":::
+
+The and methods return the actual number of elements written. They throw an exception if the destination buffer is too short to contain the result. There are non-throwing and methods as well for callers who want to avoid exceptions.
+
+## Rune in .NET vs. other languages
+
+The term "rune" is not defined in the Unicode Standard. The term dates back to [the creation of UTF-8](https://www.cl.cam.ac.uk/~mgk25/ucs/utf-8-history.txt). Rob Pike and Ken Thompson were looking for a term to describe what would eventually become known as a code point. [They settled on the term "rune"](https://twitter.com/rob_pike/status/732353233474064384), and Rob Pike's later influence over the Go programming language helped popularize the term.
+
+However, the .NET `Rune` type is not the equivalent of the Go `rune` type. In Go, the `rune` type is an [alias for `int32`](https://blog.golang.org/strings). A Go rune is intended to represent a Unicode code point, but it can be any 32-bit value, including surrogate code points and values that are not legal Unicode code points.
+
+For similar types in other programming languages, see [Rust's primitive `char` type](https://doc.rust-lang.org/std/primitive.char.html) or [Swift's `Unicode.Scalar` type](https://developer.apple.com/documentation/swift/unicode/scalar), both of which represent Unicode scalar values. They provide functionality similar to .NET's `Rune` type, and they disallow instantiation of values that are not legal Unicode scalar values.
+
+ ]]>
+
diff --git a/xml/System.Text/StringBuilder.xml b/xml/System.Text/StringBuilder.xml
index e7a95437c29..7a6691a92f9 100644
--- a/xml/System.Text/StringBuilder.xml
+++ b/xml/System.Text/StringBuilder.xml
@@ -64,7 +64,206 @@
Represents a mutable string of characters. This class cannot be inherited.
- For more information about this API, see Supplemental API remarks for StringBuilder.
+
+ class represents a string-like object whose value is a mutable sequence of characters.
+
+## StringBuilder versus String type
+
+Although and both represent sequences of characters, they are implemented differently. is an immutable type. That is, each operation that appears to modify a object actually creates a new string.
+
+For example, the call to the method in the following C# example appears to change the value of a string variable named `value`. In fact, the method returns a `value` object that has a different value and address from the `value` object that was passed to the method. Note that the example must be compiled using the `/unsafe` compiler option.
+
+:::code language="csharp" source="~/snippets/csharp/System.Text/StringBuilder/Overview/immutability2.cs" id="Snippet1":::
+:::code language="fsharp" source="~/snippets/fsharp/System.Text/StringBuilder/Overview/immutability2.fs" id="Snippet1":::
+
+For routines that perform extensive string manipulation (such as apps that modify a string numerous times in a loop), modifying a string repeatedly can exert a significant performance penalty. The alternative is to use , which is a mutable string class. Mutability means that once an instance of the class has been created, it can be modified by appending, removing, replacing, or inserting characters.
+
+> [!IMPORTANT]
+> Although the class generally offers better performance than the class, you should not automatically replace with whenever you want to manipulate strings. Performance depends on the size of the string, the amount of memory to be allocated for the new string, the system on which your code is executing, and the type of operation. You should be prepared to test your code to determine whether actually offers a significant performance improvement.
+
+Consider using the class under these conditions:
+
+- When the number of changes that your code will make to a string is small. In these cases, might offer negligible or no performance improvement over .
+- When you perform a fixed number of concatenation operations, particularly with string literals. In this case, the compiler might combine the concatenation operations into a single operation.
+- When you have to perform extensive search operations while you are building your string. The class lacks search methods such as `IndexOf` or `StartsWith`. You'll have to convert the object to a for these operations, and this can negate the performance benefit from using . For more information, see the [Search the text in a StringBuilder object](#search-the-text-in-a-stringbuilder-object) section.
+
+Consider using the class under these conditions:
+
+- When you expect your code to make an unknown number of changes to a string at design time (for example, when you use a loop to concatenate a random number of strings that contain user input).
+- When you expect your code to make a significant number of changes to a string.
+
+## How StringBuilder works
+
+The property indicates the number of characters the object currently contains. If you add characters to the object, its length increases until it equals the size of the property, which defines the number of characters that the object can contain. If the number of added characters causes the length of the object to exceed its current capacity, new memory is allocated, the value of the property is doubled, new characters are added to the object, and its property is adjusted. Additional memory for the object is allocated dynamically until it reaches the value defined by the property. When the maximum capacity is reached, no further memory can be allocated for the object, and trying to add characters or expand it beyond its maximum capacity throws either an or an exception.
+
+The following example illustrates how a object allocates new memory and increases its capacity dynamically as the string assigned to the object expands. The code creates a object by calling its default (parameterless) constructor. The default capacity of this object is 16 characters, and its maximum capacity is more than 2 billion characters. Appending the string "This is a sentence." results in a new memory allocation because the string length (19 characters) exceeds the default capacity of the object. The capacity of the object doubles to 32 characters, the new string is added, and the length of the object now equals 19 characters. The code then appends the string "This is an additional sentence." to the value of the object 11 times. Whenever the append operation causes the length of the object to exceed its capacity, its existing capacity is doubled and the operation succeeds.
+
+:::code language="csharp" source="~/snippets/csharp/System.Text/StringBuilder/Overview/default1.cs" id="Snippet3":::
+:::code language="fsharp" source="~/snippets/fsharp/System.Text/StringBuilder/Overview/default1.fs" id="Snippet3":::
+:::code language="vb" source="~/snippets/visualbasic/System.Text/StringBuilder/Overview/default1.vb" id="Snippet3":::
+
+## Memory allocation
+
+The default capacity of a object is 16 characters, and its default maximum capacity is . These default values are used if you call the and constructors.
+
+You can explicitly define the initial capacity of a object in the following ways:
+
+- By calling any of the constructors that includes a `capacity` parameter when you create the object.
+- By explicitly assigning a new value to the property to expand an existing object. (The property throws an exception if the new capacity is less than the existing capacity or greater than the object's maximum capacity.)
+- By calling the method with the new capacity. The new capacity must not be greater than the object's maximum capacity. However, unlike an assignment to the property, does not throw an exception if the desired new capacity is less than the existing capacity. In this case, the method call has no effect.
+
+If the length of the string assigned to the object in the constructor call exceeds either the default capacity or the specified capacity, the property is set to the length of the string specified with the `value` parameter.
+
+You can explicitly define the maximum capacity of a object by calling the constructor. You can't change the maximum capacity by assigning a new value to the property, because it is read-only.
+
+As the previous section shows, whenever the existing capacity is inadequate, additional memory is allocated and the capacity of a object doubles up to the value defined by the property.
+
+In general, the default capacity and maximum capacity are adequate for most apps. You might consider setting these values under the following conditions:
+
+- If the eventual size of the object is likely to grow exceedingly large, typically in excess of several megabytes. In this case, there might be some performance benefit from setting the initial property to a significantly high value to eliminate the need for too many memory reallocations.
+- If your code is running on a system with limited memory. In this case, you might consider setting the property to less than if your code is handling large strings that might cause it to execute in a memory-constrained environment.
+
+## Instantiate a StringBuilder object
+
+You instantiate a object by calling one of its six overloaded class constructors, which are listed in the following table. Three of the constructors instantiate a object whose value is an empty string, but set its and values differently. The remaining three constructors define a object that has a specific string value and capacity. Two of the three constructors use the default maximum capacity of , whereas the third allows you to set the maximum capacity.
+
+| Constructor | String value | Capacity | Maximum capacity |
+|-------------|--------------|----------|------------------|
+|||16||
+|||Defined by the `capacity` parameter||
+|||Defined by the `capacity` parameter|Defined by the `maxCapacity` parameter|
+||Defined by the `value` parameter|16 or `value`. , whichever is greater||
+||Defined by the `value` parameter|Defined by the `capacity` parameter or `value`. , whichever is greater.||
+||Defined by `value`. (`startIndex`, `length`)|Defined by the `capacity` parameter or `value`. , whichever is greater.||
+
+The following example uses three of these constructor overloads to instantiate objects.
+
+:::code language="csharp" source="~/snippets/csharp/System.Text/StringBuilder/Overview/instantiate1.cs" id="Snippet6":::
+:::code language="fsharp" source="~/snippets/fsharp/System.Text/StringBuilder/Overview/instantiate1.fs" id="Snippet6":::
+:::code language="vb" source="~/snippets/visualbasic/System.Text/StringBuilder/Overview/instantiate1.vb" id="Snippet6":::
+
+## Call StringBuilder methods
+
+Most of the methods that modify the string in a instance return a reference to that same instance. This enables you to call methods in two ways:
+
+- You can make individual method calls and ignore the return value, as the following example does.
+
+ :::code language="csharp" source="~/snippets/csharp/System.Text/StringBuilder/Overview/call1.cs" id="Snippet4":::
+ :::code language="fsharp" source="~/snippets/fsharp/System.Text/StringBuilder/Overview/call1.fs" id="Snippet4":::
+ :::code language="vb" source="~/snippets/visualbasic/System.Text/StringBuilder/Overview/call1.vb" id="Snippet4":::
+
+- You can make a series of method calls in a single statement. This can be convenient if you want to write a single statement that chains successive operations. The following example consolidates three method calls from the previous example into a single line of code.
+
+ :::code language="csharp" source="~/snippets/csharp/System.Text/StringBuilder/Overview/call2.cs" id="Snippet5":::
+ :::code language="fsharp" source="~/snippets/fsharp/System.Text/StringBuilder/Overview/call2.fs" id="Snippet5":::
+ :::code language="vb" source="~/snippets/visualbasic/System.Text/StringBuilder/Overview/call2.vb" id="Snippet5":::
+
+## Perform StringBuilder operations
+
+You can use the methods of the class to iterate, add, delete, or modify characters in a object.
+
+### Iterate StringBuilder characters
+
+You can access the characters in a object by using the property. In C#, is an indexer; in Visual Basic, it is the default property of the class. This enables you to set or retrieve individual characters by using their index only, without explicitly referencing the property. Characters in a object begin at index 0 (zero) and continue to index - 1.
+
+The following example illustrates the property. It appends ten random numbers to a object, and then iterates each character. If the character's Unicode category is , it decreases the number by 1 (or changes the number to 9 if its value is 0). The example displays the contents of the object both before and after the values of individual characters were changed.
+
+:::code language="csharp" source="~/snippets/csharp/System.Text/StringBuilder/Overview/chars1.cs" id="Snippet7":::
+:::code language="fsharp" source="~/snippets/fsharp/System.Text/StringBuilder/Overview/chars1.fs" id="Snippet7":::
+:::code language="vb" source="~/snippets/visualbasic/System.Text/StringBuilder/Overview/chars1.vb" id="Snippet7":::
+
+[!INCLUDE[stringbuilder-performance-note](~/includes/stringbuilder-perf-note.md)]
+
+### Add text to a StringBuilder object
+
+The class includes the following methods for expanding the contents of a object:
+
+- The method appends a string, a substring, a character array, a portion of a character array, a single character repeated multiple times, or the string representation of a primitive data type to a object.
+
+- The method appends a line terminator or a string along with a line terminator to a object.
+
+- The method appends a [composite format string](/dotnet/standard/base-types/composite-formatting) to a object. The string representations of objects included in the result string can reflect the formatting conventions of the current system culture or a specified culture.
+
+- The method inserts a string, a substring, multiple repetitions of a string, a character array, a portion of a character array, or the string representation of a primitive data type at a specified position in the object. The position is defined by a zero-based index.
+
+The following example uses the , , , and methods to expand the text of a object.
+
+ :::code language="csharp" source="~/snippets/csharp/System.Text/StringBuilder/Overview/expand1.cs" id="Snippet9":::
+ :::code language="fsharp" source="~/snippets/fsharp/System.Text/StringBuilder/Overview/expand1.fs" id="Snippet9":::
+ :::code language="vb" source="~/snippets/visualbasic/System.Text/StringBuilder/Overview/expand1.vb" id="Snippet9":::
+
+### Delete text from a StringBuilder object
+
+The class includes methods that can reduce the size of the current instance. The method removes all characters and sets the property to zero. The method deletes a specified number of characters starting at a particular index position. In addition, you can remove characters from the end of a object by setting its property to a value that is less than the length of the current instance.
+
+The following example removes some of the text from a object, displays its resulting capacity, maximum capacity, and length property values, and then calls the method to remove all the characters from the object.
+
+:::code language="csharp" source="~/snippets/csharp/System.Text/StringBuilder/Overview/delete1.cs" id="Snippet10":::
+:::code language="fsharp" source="~/snippets/fsharp/System.Text/StringBuilder/Overview/delete1.fs" id="Snippet10":::
+:::code language="vb" source="~/snippets/visualbasic/System.Text/StringBuilder/Overview/delete1.vb" id="Snippet10":::
+
+### Modify the text in a StringBuilder object
+
+The method replaces all occurrences of a character or a string in the entire object or in a particular character range. The following example uses the method to replace all exclamation points (!) with question marks (?) in the object.
+
+:::code language="csharp" source="~/snippets/csharp/System.Text/StringBuilder/Overview/replace1.cs" id="Snippet11":::
+:::code language="fsharp" source="~/snippets/fsharp/System.Text/StringBuilder/Overview/replace1.fs" id="Snippet11":::
+:::code language="vb" source="~/snippets/visualbasic/System.Text/StringBuilder/Overview/replace1.vb" id="Snippet11":::
+
+## Search the text in a StringBuilder object
+
+The class does not include methods similar to the , , and methods provided by the class, which allow you to search the object for a particular character or a substring. Determining the presence or starting character position of a substring requires that you search a value by using either a string search method or a regular expression method. There are four ways to implement such searches, as the following table shows.
+
+| Technique | Pros | Cons |
+|-----------|------|------|
+|Search string values before adding them to the object.|Useful for determining whether a substring exists.|Cannot be used when the index position of a substring is important.|
+|Call and search the returned object.|Easy to use if you assign all the text to a object, and then begin to modify it.|Cumbersome to repeatedly call if you must make modifications before all text is added to the object.
You must remember to work from the end of the object's text if you're making changes.|
+|Use the property to sequentially search a range of characters.|Useful if you're concerned with individual characters or a small substring.|Cumbersome if the number of characters to search is large or if the search logic is complex.
Results in very poor performance for objects that have grown very large through repeated method calls. |
+|Convert the object to a object, and perform modifications on the object.|Useful if the number of modifications is small.|Negates the performance benefit of the class if the number of modifications is large.|
+
+Let's examine these techniques in greater detail.
+
+- If the goal of the search is to determine whether a particular substring exists (that is, if you aren't interested in the position of the substring), you can search strings before storing them in the object. The following example provides one possible implementation. It defines a `StringBuilderFinder` class whose constructor is passed a reference to a object and the substring to find in the string. In this case, the example tries to determine whether recorded temperatures are in Fahrenheit or Celsius, and adds the appropriate introductory text to the beginning of the object. A random number generator is used to select an array that contains data in either degrees Celsius or degrees Fahrenheit.
+
+ :::code language="csharp" source="~/snippets/csharp/System.Text/StringBuilder/Overview/pattern1.cs" id="Snippet12":::
+ :::code language="fsharp" source="~/snippets/fsharp/System.Text/StringBuilder/Overview/pattern1.fs" id="Snippet12":::
+ :::code language="vb" source="~/snippets/visualbasic/System.Text/StringBuilder/Overview/pattern1.vb" id="Snippet12":::
+
+- Call the method to convert the object to a object. You can search the string by using methods such as or , or you can use regular expressions and the class to search for patterns. Because both and objects use UTF-16 encoding to store characters, the index positions of characters, substrings, and regular expression matches are the same in both objects. This enables you to use methods to make changes at the same position at which that text is found in the object.
+
+ > [!NOTE]
+ > If you adopt this approach, you should work from the end of the object to its beginning so that you don't have to repeatedly convert the object to a string.
+
+ The following example illustrates this approach. It stores four occurrences of each letter of the English alphabet in a object. It then converts the text to a object and uses a regular expression to identify the starting position of each four-character sequence. Finally, it adds an underscore before each four-character sequence except for the first sequence, and converts the first character of the sequence to uppercase.
+
+ :::code language="csharp" source="~/snippets/csharp/System.Text/StringBuilder/Overview/pattern2.cs" id="Snippet13":::
+ :::code language="fsharp" source="~/snippets/fsharp/System.Text/StringBuilder/Overview/pattern2.fs" id="Snippet13":::
+ :::code language="vb" source="~/snippets/visualbasic/System.Text/StringBuilder/Overview/pattern2.vb" id="Snippet13":::
+
+- Use the property to sequentially search a range of characters in a object. This approach might not be practical if the number of characters to be searched is large or the search logic is particularly complex. For the performance implications of character-by-character index-based access for very large, chunked objects, see the documentation for the property.
+
+ The following example is identical in functionality to the previous example but differs in implementation. It uses the property to detect when a character value has changed, inserts an underscore at that position, and converts the first character in the new sequence to uppercase.
+
+ :::code language="csharp" source="~/snippets/csharp/System.Text/StringBuilder/Overview/pattern3.cs" id="Snippet14":::
+ :::code language="fsharp" source="~/snippets/fsharp/System.Text/StringBuilder/Overview/pattern3.fs" id="Snippet14":::
+ :::code language="vb" source="~/snippets/visualbasic/System.Text/StringBuilder/Overview/pattern3.vb" id="Snippet14":::
+
+- Store all the unmodified text in the object, call the method to convert the object to a object, and perform the modifications on the object. You can use this approach if you have only a few modifications; otherwise, the cost of working with immutable strings might negate the performance benefits of using a object.
+
+ The following example is identical in functionality to the previous two examples but differs in implementation. It creates a object, converts it to a object, and then uses a regular expression to perform all remaining modifications on the string. The method uses a lambda expression to perform the replacement on each match.
+
+ :::code language="csharp" source="~/snippets/csharp/System.Text/StringBuilder/Overview/pattern4.cs" id="Snippet15":::
+ :::code language="fsharp" source="~/snippets/fsharp/System.Text/StringBuilder/Overview/pattern4.fs" id="Snippet15":::
+ :::code language="vb" source="~/snippets/visualbasic/System.Text/StringBuilder/Overview/pattern4.vb" id="Snippet15":::
+
+## Convert the StringBuilder object to a string
+
+You must convert the object to a object before you can pass the string represented by the object to a method that has a parameter or display it in the user interface. You perform this conversion by calling the method. For an illustration, see the previous example, which calls the method to convert a object to a string so that it can be passed to a regular expression method.
+
+ ]]>
+ class.
diff --git a/xml/System.Threading.Tasks/Task.xml b/xml/System.Threading.Tasks/Task.xml
index d370d2fe4ce..a7cc342dc93 100644
--- a/xml/System.Threading.Tasks/Task.xml
+++ b/xml/System.Threading.Tasks/Task.xml
@@ -76,7 +76,104 @@
Represents an asynchronous operation.
- For more information about this API, see Supplemental API remarks for Task.
+
+ class represents a single operation that does not return a value and that usually executes asynchronously. objects are one of the central components of the [task-based asynchronous pattern](/dotnet/standard/asynchronous-programming-patterns/task-based-asynchronous-pattern-tap). Because the work performed by a object typically executes asynchronously on a thread pool thread rather than synchronously on the main application thread, you can use the property, as well as the , , and properties, to determine the state of a task. Most commonly, a lambda expression is used to specify the work that the task is to perform.
+
+For operations that return values, you use the class.
+
+## Task instantiation
+
+The following example creates and executes four tasks. Three tasks execute an delegate named `action`, which accepts an argument of type . A fourth task executes a lambda expression (an delegate) that is defined inline in the call to the task creation method. Each task is instantiated and run in a different way:
+
+- Task `t1` is instantiated by calling a Task class constructor, but is started by calling its method only after task `t2` has started.
+
+- Task `t2` is instantiated and started in a single method call by calling the method.
+
+- Task `t3` is instantiated and started in a single method call by calling the method.
+
+- Task `t4` is executed synchronously on the main thread by calling the method.
+
+Because task `t4` executes synchronously, it executes on the main application thread. The remaining tasks execute asynchronously typically on one or more thread pool threads.
+
+:::code language="csharp" source="~/snippets/csharp/System.Threading.Tasks/Task/Overview/startnew.cs" id="Snippet01":::
+:::code language="fsharp" source="~/snippets/fsharp/System.Threading.Tasks/Task/Overview/startnew.fs" id="Snippet01":::
+:::code language="vb" source="~/snippets/visualbasic/System.Threading.Tasks/Task/Overview/startnew.vb" id="Snippet01":::
+
+## Create and execute a task
+
+You can create instances in a variety of ways. The most common approach is to call the static method. The method provides a simple way to start a task using default values and without requiring additional parameters. The following example uses the method to start a task that loops and then displays the number of loop iterations:
+
+:::code language="csharp" source="~/snippets/csharp/System.Threading.Tasks/Task/Overview/run1.cs" id="Snippet6":::
+:::code language="fsharp" source="~/snippets/fsharp/System.Threading.Tasks/Task/Overview/run1.fs" id="Snippet6":::
+:::code language="vb" source="~/snippets/visualbasic/System.Threading.Tasks/Task/Overview/run1.vb" id="Snippet6":::
+
+An alternative is the static method. The property returns a object. Overloads of the method let you specify parameters to pass to the task creation options and a task scheduler. The following example uses the method to start a task. It is functionally equivalent to the code in the previous example.
+
+:::code language="csharp" source="~/snippets/csharp/System.Threading.Tasks/Task/Overview/startnew1.cs" id="Snippet7":::
+:::code language="fsharp" source="~/snippets/fsharp/System.Threading.Tasks/Task/Overview/startnew1.fs" id="Snippet7":::
+:::code language="vb" source="~/snippets/visualbasic/System.Threading.Tasks/Task/Overview/startnew1.vb" id="Snippet7":::
+
+For more complete examples, see [Task-based Asynchronous Programming](/dotnet/standard/parallel-programming/task-based-asynchronous-programming).
+
+## Separate task creation and execution
+
+The class also provides constructors that initialize the task but that do not schedule it for execution. For performance reasons, the or method is the preferred mechanism for creating and scheduling computational tasks, but for scenarios where creation and scheduling must be separated, you can use the constructors and then call the method to schedule the task for execution at a later time.
+
+## Wait for a task to complete
+
+Because tasks typically run asynchronously on a thread pool thread, the thread that creates and starts the task continues execution as soon as the task has been instantiated. In some cases, when the calling thread is the main application thread, the app may terminate before the task actually begins execution. In others, your application's logic may require that the calling thread continue execution only when one or more tasks have completed execution. You can synchronize the execution of the calling thread and the asynchronous tasks it launches by calling a `Wait` method to wait for one or more tasks to complete.
+
+To wait for a single task to complete, you can call its method. A call to the method blocks the calling thread until the single class instance has completed execution.
+
+The following example calls the parameterless method to wait unconditionally until a task completes. The task simulates work by calling the method to sleep for two seconds.
+
+:::code language="csharp" source="~/snippets/csharp/System.Threading.Tasks/Task/Overview/Wait1.cs" id="Snippet8":::
+:::code language="fsharp" source="~/snippets/fsharp/System.Threading.Tasks/Task/Overview/Wait1.fs" id="Snippet8":::
+:::code language="vb" source="~/snippets/visualbasic/System.Threading.Tasks/Task/Overview/Wait1.vb" id="Snippet8":::
+
+You can also conditionally wait for a task to complete. The and methods block the calling thread until the task finishes or a timeout interval elapses, whichever comes first. Since the following example launches a task that sleeps for two seconds but defines a one-second timeout value, the calling thread blocks until the timeout expires and before the task has completed execution.
+
+:::code language="csharp" source="~/snippets/csharp/System.Threading.Tasks/Task/Overview/Wait2.cs" id="Snippet9":::
+:::code language="fsharp" source="~/snippets/fsharp/System.Threading.Tasks/Task/Overview/Wait2.fs" id="Snippet9":::
+:::code language="vb" source="~/snippets/visualbasic/System.Threading.Tasks/Task/Overview/Wait2.vb" id="Snippet9":::
+
+You can also supply a cancellation token by calling the and methods. If the token's property is `true` or becomes `true` while the method is executing, the method throws an .
+
+In some cases, you may want to wait for the first of a series of executing tasks to complete, but don't care which task it is. For this purpose, you can call one of the overloads of the method. The following example creates three tasks, each of which sleeps for an interval determined by a random number generator. The method waits for the first task to complete. The example then displays information about the status of all three tasks.
+
+:::code language="csharp" source="~/snippets/csharp/System.Threading.Tasks/Task/Overview/WhenAny1.cs" id="Snippet10":::
+:::code language="fsharp" source="~/snippets/fsharp/System.Threading.Tasks/Task/Overview/WhenAny1.fs" id="Snippet10":::
+:::code language="vb" source="~/snippets/visualbasic/System.Threading.Tasks/Task/Overview/WaitAny1.vb" id="Snippet10":::
+
+You can also wait for all of a series of tasks to complete by calling the method. The following example creates ten tasks, waits for all ten to complete, and then displays their status.
+
+:::code language="csharp" source="~/snippets/csharp/System.Threading.Tasks/Task/Overview/WaitAll1.cs" id="Snippet11":::
+:::code language="fsharp" source="~/snippets/fsharp/System.Threading.Tasks/Task/Overview/WaitAll1.fs" id="Snippet11":::
+:::code language="vb" source="~/snippets/visualbasic/System.Threading.Tasks/Task/Overview/WaitAll1.vb" id="Snippet11":::
+
+Note that when you wait for one or more tasks to complete, any exceptions thrown in the running tasks are propagated on the thread that calls the `Wait` method, as the following example shows. It launches 12 tasks, three of which complete normally and three of which throw an exception. Of the remaining six tasks, three are cancelled before they start, and three are cancelled while they are executing. Exceptions are thrown in the method call and are handled by a `try`/`catch` block.
+
+:::code language="csharp" source="~/snippets/csharp/System.Threading.Tasks/Task/Overview/WaitAll2.cs" id="Snippet12":::
+:::code language="fsharp" source="~/snippets/fsharp/System.Threading.Tasks/Task/Overview/WaitAll2.fs" id="Snippet12":::
+:::code language="vb" source="~/snippets/visualbasic/System.Threading.Tasks/Task/Overview/WaitAll2.vb" id="Snippet12":::
+
+For more information on exception handling in task-based asynchronous operations, see [Exception Handling](/dotnet/standard/parallel-programming/exception-handling-task-parallel-library).
+
+## Tasks and culture
+
+Starting with desktop apps that target .NET Framework 4.6, the culture of the thread that creates and invokes a task becomes part of the thread's context. That is, regardless of the current culture of the thread on which the task executes, the current culture of the task is the culture of the calling thread. For apps that target versions of .NET Framework prior to .NET Framework 4.6, the culture of the task is the culture of the thread on which the task executes. For more information, see the "Culture and task-based asynchronous operations" section in the topic.
+
+> [!NOTE]
+> Store apps follow the Windows Runtime in setting and getting the default culture.
+
+## For debugger developers
+
+For developers implementing custom debuggers, several internal and private members of task may be useful (these may change from release to release). The `m_taskId` field serves as the backing store for the property, however accessing this field directly from a debugger may be more efficient than accessing the same value through the property's getter method (the `s_taskIdCounter` counter is used to retrieve the next available ID for a task). Similarly, the `m_stateFlags` field stores information about the current lifecycle stage of the task, information also accessible through the property. The `m_action` field stores a reference to the task's delegate, and the `m_stateObject` field stores the async state passed to the task by the developer. Finally, for debuggers that parse stack frames, the `InternalWait` method serves a potential marker for when a task is entering a wait operation.
+
+ ]]>
+ All members of , except for , are thread-safe and may be used from multiple threads concurrently.Task Parallel Library (TPL)
diff --git a/xml/System.Threading.Tasks/TaskScheduler.xml b/xml/System.Threading.Tasks/TaskScheduler.xml
index 7abfcd233c7..bb3b8953674 100644
--- a/xml/System.Threading.Tasks/TaskScheduler.xml
+++ b/xml/System.Threading.Tasks/TaskScheduler.xml
@@ -64,13 +64,70 @@
Represents an object that handles the low-level work of queuing tasks onto threads.
- For more information about this API, see Supplemental API remarks for TaskScheduler.
+
+ class represents a task scheduler. A task scheduler ensures that the work of a task is eventually executed.
+
+The default task scheduler provides work-stealing for load-balancing, thread injection/retirement for maximum throughput, and overall good performance. It should be sufficient for most scenarios.
+
+The class also serves as the extension point for all customizable scheduling logic. This includes mechanisms such as how to schedule a task for execution, and how scheduled tasks should be exposed to debuggers. If you require special functionality, you can create a custom scheduler and enable it for specific tasks or queries.
+
+## The default task scheduler and the thread pool
+
+The default scheduler for the Task Parallel Library and PLINQ uses the .NET thread pool, which is represented by the class, to queue and execute work. The thread pool uses the information that is provided by the type to efficiently support the fine-grained parallelism (short-lived units of work) that parallel tasks and queries often represent.
+
+### The global queue vs. local queues
+
+The thread pool maintains a global FIFO (first-in, first-out) work queue for threads in each application domain. Whenever a program calls the (or ) method, the work is put on this shared queue and eventually de-queued onto the next thread that becomes available. Starting with .NET Framework 4, this queue uses a lock-free algorithm that resembles the class. By using this lock-free implementation, the thread pool spends less time when it queues and de-queues work items. This performance benefit is available to all programs that use the thread pool.
+
+Top-level tasks, which are tasks that are not created in the context of another task, are put on the global queue just like any other work item. However, nested or child tasks, which are created in the context of another task, are handled quite differently. A child or nested task is put on a local queue that is specific to the thread on which the parent task is executing. The parent task may be a top-level task or it also may be the child of another task. When this thread is ready for more work, it first looks in the local queue. If work items are waiting there, they can be accessed quickly. The local queues are accessed in last-in, first-out order (LIFO) to preserve cache locality and reduce contention. For more information about child tasks and nested tasks, see [Attached and Detached Child Tasks](/dotnet/standard/parallel-programming/attached-and-detached-child-tasks).
+
+The use of local queues not only reduces pressure on the global queue, but also takes advantage of data locality. Work items in the local queue frequently reference data structures that are physically near one another in memory. In these cases, the data is already in the cache after the first task has run and can be accessed quickly. Both [Parallel LINQ (PLINQ)](/dotnet/standard/parallel-programming/parallel-linq-plinq) and the class use nested tasks and child tasks extensively, and achieve significant speedups by using the local work queues.
+
+### Work stealing
+
+Starting with .NET Framework 4, the thread pool also features a work-stealing algorithm to help make sure that no threads are sitting idle while others still have work in their queues. When a thread-pool thread is ready for more work, it first looks at the head of its local queue, then in the global queue, and then in the local queues of other threads. If it finds a work item in the local queue of another thread, it first applies heuristics to make sure that it can run the work efficiently. If it can, it de-queues the work item from the tail (in FIFO order). This reduces contention on each local queue and preserves data locality. This architecture helps the thread pool load-balance work more efficiently than past versions did.
+
+### Long-running tasks
+
+You may want to explicitly prevent a task from being put on a local queue. For example, you may know that a particular work item will run for a relatively long time and is likely to block all other work items on the local queue. In this case, you can specify the option, which provides a hint to the scheduler that an additional thread might be required for the task so that it does not block the forward progress of other threads or work items on the local queue. By using this option you avoid the thread pool completely, including the global and local queues.
+
+### Task inlining
+
+In some cases when a is waited on, it may be executed synchronously on the thread that is performing the wait operation. This enhances performance by preventing the need for an additional thread and instead using the existing thread, which would have blocked otherwise. To prevent errors due to reentrancy, task inlining only occurs when the wait target is found in the relevant thread's local queue.
+
+## Specify a synchronization context
+
+You can use the method to specify that a task should be scheduled to run on a particular thread. This is useful in frameworks such as Windows Forms and Windows Presentation Foundation where access to user interface objects is often restricted to code that is running on the same thread on which the UI object was created.
+
+The following example uses the method in a Windows Presentation Foundation (WPF) app to schedule a task on the same thread that the user interface (UI) control was created on. The example creates a mosaic of images that are randomly selected from a specified directory. The WPF objects are used to load and resize the images. The raw pixels are then passed to a task that uses a loop to write the pixel data into a large single-byte array. No synchronization is required because no two tiles occupy the same array elements. The tiles can also be written in any order because their position is calculated independently of any other tile. The large array is then passed to a task that runs on the UI thread, where the pixel data is loaded into an Image control.
+
+The example moves data off the UI thread, modifies it by using parallel loops and objects, and then passes it back to a task that runs on the UI thread. This approach is useful when you have to use the Task Parallel Library to perform operations that either are not supported by the WPF API, or are not sufficiently fast. Another way to create an image mosaic in WPF is to use a control and add images to it. The handles the work of positioning the tiles. However, this work can only be performed on the UI thread.
+
+:::code language="csharp" source="~/snippets/csharp/System.Threading.Tasks/TaskScheduler/FromCurrentSynchronizationContext/mainwindow.xaml.cs" id="Snippet01":::
+
+To create the example, create a WPF application project in Visual Studio and name it WPF_CS1 (for a C# WPF project) or WPF_VB1 (for a Visual Basic WPF project). Then do the following:
+
+1. In design view, drag an control from the **Toolbox** onto the upper left corner of the design surface. In the **Name** textbox of the **Properties** window, name the control "image".
+
+2. Drag a control from the **Toolbox** to the lower left part of the application window. In XAML view, specify the property of the button as "Make a mosaic", and specify its property as "100". Connect the event with the `button_Click` event handler defined in the example's code by adding `Click="button_Click"` to the `
+ All members of the abstract type are thread-safe and may be used from multiple threads concurrently.
diff --git a/xml/System.Threading/Monitor.xml b/xml/System.Threading/Monitor.xml
index 367d14c680b..31bc388c146 100644
--- a/xml/System.Threading/Monitor.xml
+++ b/xml/System.Threading/Monitor.xml
@@ -53,7 +53,121 @@
Provides a mechanism that synchronizes access to objects.
- For more information about this API, see Supplemental API remarks for Monitor.
+
+ class allows you to synchronize access to a region of code by taking and releasing a lock on a particular object by calling the , , and methods. Object locks provide the ability to restrict access to a block of code, commonly called a critical section. While a thread owns the lock for an object, no other thread can acquire that lock. You can also use the class to ensure that no other thread is allowed to access a section of application code being executed by the lock owner, unless the other thread is executing the code using a different locked object. Because the Monitor class has thread affinity, the thread that acquired a lock must release the lock by calling the Monitor.Exit method.
+
+## Overview
+
+ has the following features:
+
+- It is associated with an object on demand.
+- It is unbound, which means it can be called directly from any context.
+- An instance of the class cannot be created; the methods of the class are all static. Each method is passed the synchronized object that controls access to the critical section.
+
+> [!NOTE]
+> Use the class to lock objects other than strings (that is, reference types other than ), not value types. For details, see the overloads of the method and [The lock object](#the-lock-object) section later in this article.
+
+The following table describes the actions that can be taken by threads that access synchronized objects:
+
+|Action|Description|
+|------------|-----------------|
+|, |Acquires a lock for an object. This action also marks the beginning of a critical section. No other thread can enter the critical section unless it is executing the instructions in the critical section using a different locked object.|
+||Releases the lock on an object in order to permit other threads to lock and access the object. The calling thread waits while another thread accesses the object. Pulse signals are used to notify waiting threads about changes to an object's state.|
+| (signal), |Sends a signal to one or more waiting threads. The signal notifies a waiting thread that the state of the locked object has changed, and the owner of the lock is ready to release the lock. The waiting thread is placed in the object's ready queue so that it might eventually receive the lock for the object. Once the thread has the lock, it can check the new state of the object to see if the required state has been reached.|
+||Releases the lock on an object. This action also marks the end of a critical section protected by the locked object.|
+
+There are two sets of overloads for the and methods. One set of overloads has a `ref` (in C#) or `ByRef` (in Visual Basic) parameter that is atomically set to `true` if the lock is acquired, even if an exception is thrown when acquiring the lock. Use these overloads if it is critical to release the lock in all cases, even when the resources the lock is protecting might not be in a consistent state.
+
+## The lock object
+
+The Monitor class consists of `static` (`Shared` in Visual Basic) methods that operate on an object that controls access to the critical section. The following information is maintained for each synchronized object:
+
+- A reference to the thread that currently holds the lock.
+- A reference to a ready queue, which contains the threads that are ready to obtain the lock.
+- A reference to a waiting queue, which contains the threads that are waiting for notification of a change in the state of the locked object.
+
+ locks objects (that is, reference types), not value types. While you can pass a value type to and , it is boxed separately for each call. Since each call creates a separate object, never blocks, and the code it is supposedly protecting is not really synchronized. In addition, the object passed to is different from the object passed to , so throws exception with the message "Object synchronization method was called from an unsynchronized block of code."
+
+The following example illustrates this problem. It launches ten tasks, each of which just sleeps for 250 milliseconds. Each task then updates a counter variable, `nTasks`, which is intended to count the number of tasks that actually launched and executed. Because `nTasks` is a global variable that can be updated by multiple tasks simultaneously, a monitor is used to protect it from simultaneous modification by multiple tasks. However, as the output from the example shows, each of the tasks throws a exception.
+
+:::code language="csharp" source="~/snippets/csharp/System.Threading/Monitor/Overview/badlock1.cs" id="Snippet2":::
+:::code language="vb" source="~/snippets/visualbasic/System.Threading/Monitor/Overview/badlock1.vb" id="Snippet2":::
+
+Each task throws a exception because the `nTasks` variable is boxed before the call to the method in each task. In other words, each method call is passed a separate variable that is independent of the others. `nTasks` is boxed again in the call to the method. Once again, this creates ten new boxed variables, which are independent of each other, `nTasks`, and the ten boxed variables created in the call to the method. The exception is thrown, then, because our code is attempting to release a lock on a newly created variable that was not previously locked.
+
+Although you can box a value type variable before calling and , as shown in the following example, and pass the same boxed object to both methods, there is no advantage to doing this. Changes to the unboxed variable are not reflected in the boxed copy, and there is no way to change the value of the boxed copy.
+
+:::code language="csharp" source="~/snippets/csharp/System.Threading/Monitor/Overview/badbox1.cs" id="Snippet3":::
+:::code language="vb" source="~/snippets/visualbasic/System.Threading/Monitor/Overview/badbox1.vb" id="Snippet3":::
+
+When selecting an object on which to synchronize, you should lock only on private or internal objects. Locking on external objects might result in deadlocks, because unrelated code could choose the same objects to lock on for different purposes.
+
+Note that you can synchronize on an object in multiple application domains if the object used for the lock derives from .
+
+## The critical section
+
+Use the and methods to mark the beginning and end of a critical section.
+
+> [!NOTE]
+> The functionality provided by the and methods is identical to that provided by the [lock](/dotnet/csharp/language-reference/keywords/lock-statement) statement in C# and the [SyncLock](/dotnet/visual-basic/language-reference/statements/synclock-statement) statement in Visual Basic, except that the language constructs wrap the method overload and the method in a `try`…`finally` block to ensure that the monitor is released.
+
+If the critical section is a set of contiguous instructions, then the lock acquired by the method guarantees that only a single thread can execute the enclosed code with the locked object. In this case, we recommend that you place that code in a `try` block and place the call to the method in a `finally` block. This ensures that the lock is released even if an exception occurs. The following code fragment illustrates this pattern.
+
+:::code language="csharp" source="~/snippets/csharp/System.Threading/Monitor/Overview/Pattern2.cs" id="Snippet2":::
+:::code language="vb" source="~/snippets/visualbasic/System.Threading/Monitor/Overview/Pattern2.vb" id="Snippet2":::
+
+This facility is typically used to synchronize access to a static or instance method of a class.
+
+If a critical section spans an entire method, the locking facility can be achieved by placing the on the method, and specifying the value in the constructor of . When you use this attribute, the and method calls are not needed. The following code fragment illustrates this pattern:
+
+:::code language="csharp" source="~/snippets/csharp/System.Threading/Monitor/Overview/Pattern2.cs" id="Snippet3":::
+:::code language="vb" source="~/snippets/visualbasic/System.Threading/Monitor/Overview/Pattern2.vb" id="Snippet3":::
+
+Note that the attribute causes the current thread to hold the lock until the method returns; if the lock can be released sooner, use the class, the C# [lock](/dotnet/csharp/language-reference/keywords/lock-statement) statement, or the Visual Basic [SyncLock](/dotnet/visual-basic/language-reference/statements/synclock-statement) statement inside of the method instead of the attribute.
+
+While it is possible for the and statements that lock and release a given object to cross member or class boundaries or both, this practice is not recommended.
+
+## Pulse, PulseAll, and Wait
+
+Once a thread owns the lock and has entered the critical section that the lock protects, it can call the , , and methods.
+
+When the thread that holds the lock calls , the lock is released and the thread is added to the waiting queue of the synchronized object. The first thread in the ready queue, if any, acquires the lock and enters the critical section. The thread that called is moved from the waiting queue to the ready queue when either the or the method is called by the thread that holds the lock (to be moved, the thread must be at the head of the waiting queue). The method returns when the calling thread reacquires the lock.
+
+When the thread that holds the lock calls , the thread at the head of the waiting queue is moved to the ready queue. The call to the method moves all the threads from the waiting queue to the ready queue.
+
+## Monitors and wait handles
+
+It is important to note the distinction between the use of the class and objects.
+
+- The class is purely managed, fully portable, and might be more efficient in terms of operating-system resource requirements.
+- objects represent operating-system waitable objects, are useful for synchronizing between managed and unmanaged code, and expose some advanced operating-system features like the ability to wait on many objects at once.
+
+## Examples
+
+The following example uses the class to synchronize access to a single instance of a random number generator represented by the class. The example creates ten tasks, each of which executes asynchronously on a thread pool thread. Each task generates 10,000 random numbers, calculates their average, and updates two procedure-level variables that maintain a running total of the number of random numbers generated and their sum. After all tasks have executed, these two values are then used to calculate the overall mean.
+
+:::code language="csharp" source="~/snippets/csharp/System.Threading/Monitor/Overview/example1.cs" id="Snippet1":::
+:::code language="vb" source="~/snippets/visualbasic/System.Threading/Monitor/Overview/example1.vb" id="Snippet1":::
+
+Because they can be accessed from any task running on a thread pool thread, access to the variables `total` and `n` must also be synchronized. The method is used for this purpose.
+
+The following example demonstrates the combined use of the class (implemented with the `lock` or `SyncLock` language construct), the class, and the class. It defines two `internal` (in C#) or `Friend` (in Visual Basic) classes, `SyncResource` and `UnSyncResource`, that respectively provide synchronized and unsynchronized access to a resource. To ensure that the example illustrates the difference between the synchronized and unsynchronized access (which could be the case if each method call completes rapidly), the method includes a random delay: for threads whose property is even, the method calls to introduce a delay of 2,000 milliseconds. Note that, because the `SyncResource` class is not public, none of the client code takes a lock on the synchronized resource; the internal class itself takes the lock. This prevents malicious code from taking a lock on a public object.
+
+:::code language="csharp" source="~/snippets/csharp/System.Threading/Monitor/Overview/source.cs" id="Snippet1":::
+:::code language="vb" source="~/snippets/visualbasic/System.Threading/Monitor/Overview/source.vb" id="Snippet1":::
+
+The example defines a variable, `numOps`, that defines the number of threads that will attempt to access the resource. The application thread calls the method for synchronized and unsynchronized access five times each. The method has a single parameter, a delegate that accepts no parameters and returns no value. For synchronized access, it invokes the `SyncUpdateResource` method; for unsynchronized access, it invokes the `UnSyncUpdateResource` method. After each set of method calls, the application thread calls the [AutoResetEvent.WaitOne](xref:System.Threading.WaitHandle.WaitOne*) method so that it blocks until the instance is signaled.
+
+Each call to the `SyncUpdateResource` method calls the internal `SyncResource.Access` method and then calls the method to decrement the `numOps` counter. The method is used to decrement the counter, because otherwise you cannot be certain that a second thread will access the value before a first thread's decremented value has been stored in the variable. When the last synchronized worker thread decrements the counter to zero, indicating that all synchronized threads have completed accessing the resource, the `SyncUpdateResource` method calls the method, which signals the main thread to continue execution.
+
+Each call to the `UnSyncUpdateResource` method calls the internal `UnSyncResource.Access` method and then calls the method to decrement the `numOps` counter. Once again, the method is used to decrement the counter to ensure that a second thread does not access the value before a first thread's decremented value has been assigned to the variable. When the last unsynchronized worker thread decrements the counter to zero, indicating that no more unsynchronized threads need to access the resource, the `UnSyncUpdateResource` method calls the method, which signals the main thread to continue execution.
+
+As the output from the example shows, synchronized access ensures that the calling thread exits the protected resource before another thread can access it; each thread waits on its predecessor. On the other hand, without the lock, the `UnSyncResource.Access` method is called in the order in which threads reach it.
+
+ ]]>
+ This type is thread safe.Managed Threading
@@ -1274,7 +1388,63 @@
Releases the lock on an object and blocks the current thread until it reacquires the lock. If the specified time-out interval elapses, the thread enters the ready queue. This method also specifies whether the synchronization domain for the context (if in a synchronized context) is exited before the wait and reacquired afterward. if the lock was reacquired before the specified time elapsed; if the lock was reacquired after the specified time elapsed. The method does not return until the lock is reacquired.
- For more information about this API, see Supplemental API remarks for Monitor.Wait.
+
+ method
+
+This method does not return until it reacquires an exclusive lock on the `obj` parameter.
+
+The thread that currently owns the lock on the specified object invokes this method in order to release the object so that another thread can access it. The caller is blocked while waiting to reacquire the lock. This method is called when the caller needs to wait for a state change that will occur as a result of another thread's operations.
+
+The time-out ensures that the current thread does not block indefinitely if another thread releases the lock without first calling the or method. It also moves the thread to the ready queue, bypassing other threads ahead of it in the wait queue, so that it can reacquire the lock sooner. The thread can test the return value of the method to determine whether it reacquired the lock prior to the time-out. The thread can evaluate the conditions that caused it to enter the wait, and if necessary call the method again.
+
+When a thread calls `Wait`, it releases the lock and enters the waiting queue. At this point, the next thread in the ready queue (if there is one) is allowed to take control of the lock. The thread that invoked `Wait` remains in the waiting queue until either a thread that holds the lock invokes , or it is the next in the queue and a thread that holds the lock invokes . However, if `millisecondsTimeout` elapses before another thread invokes this object's or method, the original thread is moved to the ready queue in order to regain the lock.
+
+> [!NOTE]
+> If is specified for the `millisecondsTimeout` parameter, this method blocks indefinitely unless the holder of the lock calls or . If `millisecondsTimeout` equals 0, the thread that calls `Wait` releases the lock and then immediately enters the ready queue in order to regain the lock.
+
+The caller executes `Wait` once, regardless of the number of times has been invoked for the specified object. Conceptually, the `Wait` method stores the number of times the caller invoked on the object and invokes as many times as necessary to fully release the locked object. The caller then blocks while waiting to reacquire the object. When the caller reacquires the lock, the system calls as many times as necessary to restore the saved count for the caller. Calling `Wait` releases the lock for the specified object only; if the caller is the owner of locks on other objects, these locks are not released.
+
+> [!NOTE]
+> A synchronized object holds several references, including a reference to the thread that currently holds the lock, a reference to the ready queue, which contains the threads that are ready to obtain the lock, and a reference to the waiting queue, which contains the threads that are waiting for notification of a change in the object's state.
+
+The , , and `Wait` methods must be invoked from within a synchronized block of code.
+
+The remarks for the method explain what happens if is called when no threads are waiting.
+
+## method
+
+This method does not return until it reacquires an exclusive lock on the `obj` parameter.
+
+The thread that currently owns the lock on the specified object invokes this method in order to release the object so that another thread can access it. The caller is blocked while waiting to reacquire the lock. This method is called when the caller needs to wait for a state change that will occur as a result of another thread's operations.
+
+The time-out ensures that the current thread does not block indefinitely if another thread releases the lock without first calling the or method. It also moves the thread to the ready queue, bypassing other threads ahead of it in the wait queue, so that it can reacquire the lock sooner. The thread can test the return value of the method to determine whether it reacquired the lock prior to the time-out. The thread can evaluate the conditions that caused it to enter the wait, and if necessary call the method again.
+
+When a thread calls `Wait`, it releases the lock and enters the waiting queue. At this point, the next thread in the ready queue (if there is one) is allowed to take control of the lock. The thread that invoked `Wait` remains in the waiting queue until either a thread that holds the lock invokes , or it is the next in the queue and a thread that holds the lock invokes . However, if `timeout` milliseconds elapse before another thread invokes this object's or method, the original thread is moved to the ready queue in order to regain the lock.
+
+> [!NOTE]
+> If a representing -1 millisecond is specified for the `timeout` parameter, this method blocks indefinitely unless the holder of the lock calls or . If `timeout` is 0 milliseconds, the thread that calls `Wait` releases the lock and then immediately enters the ready queue in order to regain the lock.
+
+The caller executes `Wait` once, regardless of the number of times has been invoked for the specified object. Conceptually, the `Wait` method stores the number of times the caller invoked on the object and invokes as many times as necessary to fully release the locked object. The caller then blocks while waiting to reacquire the object. When the caller reacquires the lock, the system calls as many times as necessary to restore the saved count for the caller. Calling `Wait` releases the lock for the specified object only; if the caller is the owner of locks on other objects, these locks are not released.
+
+> [!NOTE]
+> A synchronized object holds several references, including a reference to the thread that currently holds the lock, a reference to the ready queue, which contains the threads that are ready to obtain the lock, and a reference to the waiting queue, which contains the threads that are waiting for notification of a change in the object's state.
+
+The , , and `Wait` methods must be invoked from within a synchronized block of code.
+
+The remarks for the method explain what happens if is called when no threads are waiting.
+
+## Exit the context
+
+The `exitContext` parameter has no effect unless the method is called from inside a nondefault managed context. This can happen if your thread is inside a call to an instance of a class derived from . Even if you are currently executing a method on a class that is not derived from , like , you can be in a nondefault context if a is on your stack in the current application domain.
+
+When your code is executing in a nondefault context, specifying `true` for `exitContext` causes the thread to exit the nondefault managed context (that is, to transition to the default context) before executing the method. It returns to the original nondefault context after the call to the method completes.
+
+This can be useful when the context-bound class has the attribute applied. In that case, all calls to members of the class are automatically synchronized, and the synchronization domain is the entire body of code for the class. If code in the call stack of a member calls the method and specifies `true` for `exitContext`, the thread exits the synchronization domain, allowing a thread that is blocked on a call to any member of the object to proceed. When the method returns, the thread that made the call must wait to reenter the synchronization domain.
+
+ ]]>
+ The parameter is . is not invoked from within a synchronized block of code.
@@ -1340,7 +1510,63 @@
Releases the lock on an object and blocks the current thread until it reacquires the lock. If the specified time-out interval elapses, the thread enters the ready queue. Optionally exits the synchronization domain for the synchronized context before the wait and reacquires the domain afterward. if the lock was reacquired before the specified time elapsed; if the lock was reacquired after the specified time elapsed. The method does not return until the lock is reacquired.
- For more information about this API, see Supplemental API remarks for Monitor.Wait.
+
+ method
+
+This method does not return until it reacquires an exclusive lock on the `obj` parameter.
+
+The thread that currently owns the lock on the specified object invokes this method in order to release the object so that another thread can access it. The caller is blocked while waiting to reacquire the lock. This method is called when the caller needs to wait for a state change that will occur as a result of another thread's operations.
+
+The time-out ensures that the current thread does not block indefinitely if another thread releases the lock without first calling the or method. It also moves the thread to the ready queue, bypassing other threads ahead of it in the wait queue, so that it can reacquire the lock sooner. The thread can test the return value of the method to determine whether it reacquired the lock prior to the time-out. The thread can evaluate the conditions that caused it to enter the wait, and if necessary call the method again.
+
+When a thread calls `Wait`, it releases the lock and enters the waiting queue. At this point, the next thread in the ready queue (if there is one) is allowed to take control of the lock. The thread that invoked `Wait` remains in the waiting queue until either a thread that holds the lock invokes , or it is the next in the queue and a thread that holds the lock invokes . However, if `millisecondsTimeout` elapses before another thread invokes this object's or method, the original thread is moved to the ready queue in order to regain the lock.
+
+> [!NOTE]
+> If is specified for the `millisecondsTimeout` parameter, this method blocks indefinitely unless the holder of the lock calls or . If `millisecondsTimeout` equals 0, the thread that calls `Wait` releases the lock and then immediately enters the ready queue in order to regain the lock.
+
+The caller executes `Wait` once, regardless of the number of times has been invoked for the specified object. Conceptually, the `Wait` method stores the number of times the caller invoked on the object and invokes as many times as necessary to fully release the locked object. The caller then blocks while waiting to reacquire the object. When the caller reacquires the lock, the system calls as many times as necessary to restore the saved count for the caller. Calling `Wait` releases the lock for the specified object only; if the caller is the owner of locks on other objects, these locks are not released.
+
+> [!NOTE]
+> A synchronized object holds several references, including a reference to the thread that currently holds the lock, a reference to the ready queue, which contains the threads that are ready to obtain the lock, and a reference to the waiting queue, which contains the threads that are waiting for notification of a change in the object's state.
+
+The , , and `Wait` methods must be invoked from within a synchronized block of code.
+
+The remarks for the method explain what happens if is called when no threads are waiting.
+
+## method
+
+This method does not return until it reacquires an exclusive lock on the `obj` parameter.
+
+The thread that currently owns the lock on the specified object invokes this method in order to release the object so that another thread can access it. The caller is blocked while waiting to reacquire the lock. This method is called when the caller needs to wait for a state change that will occur as a result of another thread's operations.
+
+The time-out ensures that the current thread does not block indefinitely if another thread releases the lock without first calling the or method. It also moves the thread to the ready queue, bypassing other threads ahead of it in the wait queue, so that it can reacquire the lock sooner. The thread can test the return value of the method to determine whether it reacquired the lock prior to the time-out. The thread can evaluate the conditions that caused it to enter the wait, and if necessary call the method again.
+
+When a thread calls `Wait`, it releases the lock and enters the waiting queue. At this point, the next thread in the ready queue (if there is one) is allowed to take control of the lock. The thread that invoked `Wait` remains in the waiting queue until either a thread that holds the lock invokes , or it is the next in the queue and a thread that holds the lock invokes . However, if `timeout` milliseconds elapse before another thread invokes this object's or method, the original thread is moved to the ready queue in order to regain the lock.
+
+> [!NOTE]
+> If a representing -1 millisecond is specified for the `timeout` parameter, this method blocks indefinitely unless the holder of the lock calls or . If `timeout` is 0 milliseconds, the thread that calls `Wait` releases the lock and then immediately enters the ready queue in order to regain the lock.
+
+The caller executes `Wait` once, regardless of the number of times has been invoked for the specified object. Conceptually, the `Wait` method stores the number of times the caller invoked on the object and invokes as many times as necessary to fully release the locked object. The caller then blocks while waiting to reacquire the object. When the caller reacquires the lock, the system calls as many times as necessary to restore the saved count for the caller. Calling `Wait` releases the lock for the specified object only; if the caller is the owner of locks on other objects, these locks are not released.
+
+> [!NOTE]
+> A synchronized object holds several references, including a reference to the thread that currently holds the lock, a reference to the ready queue, which contains the threads that are ready to obtain the lock, and a reference to the waiting queue, which contains the threads that are waiting for notification of a change in the object's state.
+
+The , , and `Wait` methods must be invoked from within a synchronized block of code.
+
+The remarks for the method explain what happens if is called when no threads are waiting.
+
+## Exit the context
+
+The `exitContext` parameter has no effect unless the method is called from inside a nondefault managed context. This can happen if your thread is inside a call to an instance of a class derived from . Even if you are currently executing a method on a class that is not derived from , like , you can be in a nondefault context if a is on your stack in the current application domain.
+
+When your code is executing in a nondefault context, specifying `true` for `exitContext` causes the thread to exit the nondefault managed context (that is, to transition to the default context) before executing the method. It returns to the original nondefault context after the call to the method completes.
+
+This can be useful when the context-bound class has the attribute applied. In that case, all calls to members of the class are automatically synchronized, and the synchronization domain is the entire body of code for the class. If code in the call stack of a member calls the method and specifies `true` for `exitContext`, the thread exits the synchronization domain, allowing a thread that is blocked on a call to any member of the object to proceed. When the method returns, the thread that made the call must wait to reenter the synchronization domain.
+
+ ]]>
+ The parameter is . is not invoked from within a synchronized block of code.
diff --git a/xml/System.Threading/ReaderWriterLockSlim.xml b/xml/System.Threading/ReaderWriterLockSlim.xml
index 6c5fae0a7b6..e3299883ff9 100644
--- a/xml/System.Threading/ReaderWriterLockSlim.xml
+++ b/xml/System.Threading/ReaderWriterLockSlim.xml
@@ -50,7 +50,137 @@
Represents a lock that is used to manage access to a resource, allowing multiple threads for reading or exclusive access for writing.
- For more information about this API, see Supplemental API remarks for ReaderWriterLockSlim.
+
+ to protect a resource that is read by multiple threads and written to by one thread at a time. allows multiple threads to be in read mode, allows one thread to be in write mode with exclusive ownership of the lock, and allows one thread that has read access to be in upgradeable read mode, from which the thread can upgrade to write mode without having to relinquish its read access to the resource.
+
+> [!NOTE]
+>
+> - is similar to , but it has simplified rules for recursion and for upgrading and downgrading lock state. avoids many cases of potential deadlock. In addition, the performance of is significantly better than . is recommended for all new development.
+> - is not thread-abort safe. You should not use it in an environment where threads accessing it can be aborted, such as .NET Framework. If you're using .NET Core or .NET 5+, it should be fine. is not supported in .NET Core and [is obsolete](/dotnet/core/compatibility/core-libraries/5.0/thread-abort-obsolete) in .NET 5 and later versions.
+
+By default, new instances of are created with the flag and do not allow recursion. This default policy is recommended for all new development, because recursion introduces unnecessary complications and makes your code more prone to deadlocks. To simplify migration from existing projects that use or , you can use the flag to create instances of that allow recursion.
+
+A thread can enter the lock in three modes: read mode, write mode, and upgradeable read mode. (In the rest of this topic, "upgradeable read mode" is referred to as "upgradeable mode", and the phrase "enter `x` mode" is used in preference to the longer phrase "enter the lock in `x` mode".)
+
+Regardless of recursion policy, only one thread can be in write mode at any time. When a thread is in write mode, no other thread can enter the lock in any mode. Only one thread can be in upgradeable mode at any time. Any number of threads can be in read mode, and there can be one thread in upgradeable mode while other threads are in read mode.
+
+> [!IMPORTANT]
+> This type implements the interface. When you have finished using the type, you should dispose of it either directly or indirectly. To dispose of the type directly, call its method in a `try`/`catch` block. To dispose of it indirectly, use a language construct such as `using` (in C#) or `Using` (in Visual Basic). For more information, see the "Using an Object that Implements IDisposable" section in the interface topic.
+
+ has managed thread affinity; that is, each object must make its own method calls to enter and exit lock modes. No thread can change the mode of another thread.
+
+If a does not allow recursion, a thread that tries to enter the lock can block for several reasons:
+
+- A thread that tries to enter read mode blocks if there are threads waiting to enter write mode or if there is a single thread in write mode.
+
+ > [!NOTE]
+ > Blocking new readers when writers are queued is a lock fairness policy that favors writers. The current fairness policy balances fairness to readers and writers, to promote throughput in the most common scenarios. Future versions of .NET may introduce new fairness policies.
+
+- A thread that tries to enter upgradeable mode blocks if there is already a thread in upgradeable mode, if there are threads waiting to enter write mode, or if there is a single thread in write mode.
+
+- A thread that tries to enter write mode blocks if there is a thread in any of the three modes.
+
+## Upgrade and downgrade locks
+
+Upgradeable mode is intended for cases where a thread usually reads from the protected resource, but might need to write to it if some condition is met. A thread that has entered a in upgradeable mode has read access to the protected resource, and can upgrade to write mode by calling the or methods. Because there can be only one thread in upgradeable mode at a time, upgrading to write mode cannot deadlock when recursion is not allowed, which is the default policy.
+
+> [!IMPORTANT]
+> Regardless of recursion policy, a thread that initially entered read mode is not allowed to upgrade to upgradeable mode or write mode, because that pattern creates a strong probability of deadlocks. For example, if two threads in read mode both try to enter write mode, they will deadlock. Upgradeable mode is designed to avoid such deadlocks.
+
+If there are other threads in read mode, the thread that is upgrading blocks. While the thread is blocked, other threads that try to enter read mode are blocked. When all threads have exited from read mode, the blocked upgradeable thread enters write mode. If there are other threads waiting to enter write mode, they remain blocked, because the single thread that is in upgradeable mode prevents them from gaining exclusive access to the resource.
+
+When the thread in upgradeable mode exits write mode, other threads that are waiting to enter read mode can do so, unless there are threads waiting to enter write mode. The thread in upgradeable mode can upgrade and downgrade indefinitely, as long as it is the only thread that writes to the protected resource.
+
+> [!IMPORTANT]
+> If you allow multiple threads to enter write mode or upgradeable mode, you must not allow one thread to monopolize upgradeable mode. Otherwise, threads that try to enter write mode directly will be blocked indefinitely, and while they are blocked, other threads will be unable to enter read mode.
+
+A thread in upgradeable mode can downgrade to read mode by first calling the method and then calling the method. This downgrade pattern is allowed for all lock recursion policies, even .
+
+After downgrading to read mode, a thread cannot reenter upgradeable mode until it has exited from read mode.
+
+## Enter the lock recursively
+
+You can create a that supports recursive lock entry by using the constructor that specifies lock policy, and specifying .
+
+> [!NOTE]
+> The use of recursion is not recommended for new development, because it introduces unnecessary complications and makes your code more prone to deadlocks.
+
+For a that allows recursion, the following can be said about the modes a thread can enter:
+
+- A thread in read mode can enter read mode recursively, but cannot enter write mode or upgradeable mode. If it tries to do this, a is thrown. Entering read mode and then entering write mode or upgradeable mode is a pattern with a strong probability of deadlocks, so it is not allowed. As discussed earlier, upgradeable mode is provided for cases where it is necessary to upgrade a lock.
+
+- A thread in upgradeable mode can enter write mode and/or read mode, and can enter any of the three modes recursively. However, an attempt to enter write mode blocks if there are other threads in read mode.
+
+- A thread in write mode can enter read mode and/or upgradeable mode, and can enter any of the three modes recursively.
+
+- A thread that has not entered the lock can enter any mode. This attempt can block for the same reasons as an attempt to enter a non-recursive lock.
+
+A thread can exit the modes it has entered in any order, as long as it exits each mode exactly as many times as it entered that mode. If a thread tries to exit a mode too many times, or to exit a mode it has not entered, a is thrown.
+
+## Lock states
+
+You may find it useful to think of the lock in terms of its states. A can be in one of four states: not entered, read, upgrade, and write.
+
+- Not entered: In this state, no threads have entered the lock (or all threads have exited the lock).
+
+- Read: In this state, one or more threads have entered the lock for read access to the protected resource.
+
+ > [!NOTE]
+ > A thread can enter the lock in read mode by using the or methods, or by downgrading from upgradeable mode.
+
+- Upgrade: In this state, one thread has entered the lock for read access with the option to upgrade to write access (that is, in upgradeable mode), and zero or more threads have entered the lock for read access. No more than one thread at a time can enter the lock with the option to upgrade; additional threads that try to enter upgradeable mode are blocked.
+
+- Write: In this state, one thread has entered the lock for write access to the protected resource. That thread has exclusive possession of the lock. Any other thread that tries to enter the lock for any reason is blocked.
+
+The following table describes the transitions between lock states, for locks that do not allow recursion, when a thread `t` takes the action described in the leftmost column. At the time it takes the action, `t` has no mode. (The special case where `t` is in upgradeable mode is described in the table footnotes.) The top row describes the starting state of the lock. The cells describe what happens to the thread, and show changes to the lock state in parentheses.
+
+| Transition | Not entered (N) | Read (R) | Upgrade (U) | Write (W) |
+|------------|-----------------|----------|-------------|-----------|
+|`t` enters read mode|`t` enters (R).|`t` blocks if threads are waiting for write mode; otherwise, `t` enters.|`t` blocks if threads are waiting for write mode; otherwise, `t` enters.1|`t` blocks.|
+|`t` enters upgradeable mode|`t` enters (U).|`t` blocks if threads are waiting for write mode or upgrade mode; otherwise, `t` enters (U).|`t` blocks.|`t` blocks.|
+|`t` enters write mode|`t` enters (W).|`t` blocks.|`t` blocks.2|`t` blocks.|
+
+1 If `t` starts out in upgradeable mode, it enters read mode. This action never blocks. The lock state does not change. (The thread can then complete a downgrade to read mode by exiting upgradeable mode.)
+
+2 If `t` starts out in upgradeable mode, it blocks if there are threads in read mode. Otherwise it upgrades to write mode. The lock state changes to Write (W). If `t` blocks because there are threads in read mode, it enters write mode as soon as the last thread exits read mode, even if there are threads waiting to enter write mode.
+
+When a state change occurs because a thread exits the lock, the next thread to be awakened is selected as follows:
+
+- First, a thread that is waiting for write mode and is already in upgradeable mode (there can be at most one such thread).
+- Failing that, a thread that is waiting for write mode.
+- Failing that, a thread that is waiting for upgradeable mode.
+- Failing that, all threads that are waiting for read mode.
+
+The subsequent state of the lock is always Write (W) in the first two cases and Upgrade (U) in the third case, regardless of the state of the lock when the exiting thread triggered the state change. In the last case, the state of the lock is Upgrade (U) if there is a thread in upgradeable mode after the state change, and Read (R) otherwise, regardless of the prior state.
+
+## Examples
+
+The following example shows a simple synchronized cache that holds strings with integer keys. An instance of is used to synchronize access to the that serves as the inner cache.
+
+The example includes simple methods to add to the cache, delete from the cache, and read from the cache. To demonstrate time-outs, the example includes a method that adds to the cache only if it can do so within a specified time-out.
+
+To demonstrate upgradeable mode, the example includes a method that retrieves the value associated with a key and compares it with a new value. If the value is unchanged, the method returns a status indicating no change. If no value is found for the key, the key/value pair is inserted. If the value has changed, it is updated. Upgradeable mode allows the thread to upgrade from read access to write access as needed, without the risk of deadlocks.
+
+The example includes a nested enumeration that specifies the return values for the method that demonstrates upgradeable mode.
+
+The example uses the parameterless constructor to create the lock, so recursion is not allowed. Programming the is simpler and less prone to error when the lock does not allow recursion.
+
+:::code language="csharp" source="~/snippets/csharp/System.Threading/ReaderWriterLockSlim/Overview/classexample1.cs" id="Snippet11":::
+:::code language="vb" source="~/snippets/visualbasic/System.Threading/ReaderWriterLockSlim/Overview/classexample1.vb" id="Snippet11":::
+:::code language="csharp" source="~/snippets/csharp/System.Threading/ReaderWriterLockSlim/Overview/classexample1.cs" id="Snippet12":::
+:::code language="vb" source="~/snippets/visualbasic/System.Threading/ReaderWriterLockSlim/Overview/classexample1.vb" id="Snippet12":::
+
+The following code then uses the `SynchronizedCache` object to store a dictionary of vegetable names. It creates three tasks. The first writes the names of vegetables stored in an array to a `SynchronizedCache` instance. The second and third task display the names of the vegetables, the first in ascending order (from low index to high index), the second in descending order. The final task searches for the string "cucumber" and, when it finds it, calls the method to substitute the string "green bean".
+
+:::code language="csharp" source="~/snippets/csharp/System.Threading/ReaderWriterLockSlim/Overview/classexample1.cs" id="Snippet11":::
+:::code language="vb" source="~/snippets/visualbasic/System.Threading/ReaderWriterLockSlim/Overview/classexample1.vb" id="Snippet11":::
+:::code language="csharp" source="~/snippets/csharp/System.Threading/ReaderWriterLockSlim/Overview/classexample1.cs" id="Snippet13":::
+:::code language="vb" source="~/snippets/visualbasic/System.Threading/ReaderWriterLockSlim/Overview/classexample1.vb" id="Snippet13":::
+
+ ]]>
+ This type is thread safe.
diff --git a/xml/System.Threading/Thread.xml b/xml/System.Threading/Thread.xml
index 969aab35bc9..f5560aa66f0 100644
--- a/xml/System.Threading/Thread.xml
+++ b/xml/System.Threading/Thread.xml
@@ -63,7 +63,165 @@
Creates and controls a thread, sets its priority, and gets its status.
- For more information about this API, see Supplemental API remarks for Thread.
+
+ class creates and controls a thread, sets its priority, and gets its status.
+
+When a process starts, the common language runtime automatically creates a single foreground thread to execute application code. Along with this main foreground thread, a process can create one or more threads to execute a portion of the program code associated with the process. These threads can execute either in the foreground or in the background. In addition, you can use the class to execute code on worker threads that are managed by the common language runtime.
+
+## Start a thread
+
+You start a thread by supplying a delegate that represents the method the thread is to execute in its class constructor. You then call the method to begin execution.
+
+The constructors can take either of two delegate types, depending on whether you can pass an argument to the method to be executed:
+
+- If the method has no arguments, you pass a delegate to the constructor. It has the signature:
+
+ ```csharp
+ public delegate void ThreadStart()
+ ```
+
+ ```vb
+ Public Delegate Sub ThreadStart()
+ ```
+
+ The following example creates and starts a thread that executes the `ExecuteInForeground` method. The method displays information about some thread properties, then executes a loop in which it pauses for half a second and displays the elapsed number of seconds. When the thread has executed for at least five seconds, the loop ends and the thread terminates execution.
+
+ :::code language="csharp" source="~/snippets/csharp/System.Threading/Thread/Overview/ThreadStart1.cs" id="Snippet1":::
+ :::code language="fsharp" source="~/snippets/fsharp/System.Threading/Thread/Overview/ThreadStart1.fs" id="Snippet1":::
+ :::code language="vb" source="~/snippets/visualbasic/System.Threading/Thread/Overview/ThreadStart1.vb" id="Snippet1":::
+
+- If the method has an argument, you pass a delegate to the constructor. It has the signature:
+
+ ```csharp
+ public delegate void ParameterizedThreadStart(object obj)
+ ```
+
+ ```vb
+ Public Delegate Sub ParameterizedThreadStart(obj As Object)
+ ```
+
+ The method executed by the delegate can then cast (in C#) or convert (in Visual Basic) the parameter to the appropriate type.
+
+ The following example is identical to the previous one, except that it calls the constructor. This version of the `ExecuteInForeground` method has a single parameter that represents the approximate number of milliseconds the loop is to execute.
+
+ :::code language="csharp" source="~/snippets/csharp/System.Threading/Thread/Overview/ThreadStart2.cs" id="Snippet2":::
+ :::code language="fsharp" source="~/snippets/fsharp/System.Threading/Thread/Overview/ThreadStart2.fs" id="Snippet2":::
+ :::code language="vb" source="~/snippets/visualbasic/System.Threading/Thread/Overview/ThreadStart2.vb" id="Snippet2":::
+
+It isn't necessary to retain a reference to a object once you've started the thread. The thread continues to execute until the thread procedure is complete.
+
+## Retrieve Thread objects
+
+You can use the static (`Shared` in Visual Basic) property to retrieve a reference to the currently executing thread from the code that the thread is executing. The following example uses the property to display information about the main application thread, another foreground thread, a background thread, and a thread pool thread.
+
+:::code language="csharp" source="~/snippets/csharp/System.Threading/Thread/Overview/Instance1.cs" id="Snippet4":::
+:::code language="fsharp" source="~/snippets/fsharp/System.Threading/Thread/Overview/Instance1.fs" id="Snippet4":::
+:::code language="vb" source="~/snippets/visualbasic/System.Threading/Thread/Overview/Instance1.vb" id="Snippet4":::
+
+## Foreground and background threads
+
+Instances of the class represent either foreground threads or background threads. Background threads are identical to foreground threads with one exception: a background thread does not keep a process running if all foreground threads have terminated. Once all foreground threads have been stopped, the runtime stops all background threads and shuts down.
+
+By default, the following threads execute in the foreground:
+
+- The main application thread.
+
+- All threads created by calling a class constructor.
+
+The following threads execute in the background by default:
+
+- Thread pool threads, which come from a pool of worker threads maintained by the runtime. You can configure the thread pool and schedule work on thread pool threads by using the class.
+
+ > [!NOTE]
+ > Task-based asynchronous operations automatically execute on thread pool threads. Task-based asynchronous operations use the and classes to implement the [task-based asynchronous pattern](/dotnet/standard/asynchronous-programming-patterns/task-based-asynchronous-pattern-tap).
+
+- All threads that enter the managed execution environment from unmanaged code.
+
+You can change a thread to execute in the background by setting the property at any time. Background threads are useful for any operation that should continue as long as an application is running but should not prevent the application from terminating, such as monitoring file system changes or incoming socket connections.
+
+The following example illustrates the difference between foreground and background threads. It's like the first example in the [Start a thread](#start-a-thread) section, except that it sets the thread to execute in the background before starting it. As the output shows, the loop is interrupted before it executes for five seconds.
+
+:::code language="csharp" source="~/snippets/csharp/System.Threading/Thread/Overview/BackgroundEx1.cs" id="Snippet3":::
+:::code language="fsharp" source="~/snippets/fsharp/System.Threading/Thread/Overview/BackgroundEx1.fs" id="Snippet3":::
+:::code language="vb" source="~/snippets/visualbasic/System.Threading/Thread/Overview/BackgroundEx1.vb" id="Snippet3":::
+
+## Culture and threads
+
+Each thread has a culture, represented by the property, and a UI culture, represented by the property. The current culture supports culture-sensitive operations, such as parsing and formatting, string comparison, and sorting, and also controls the writing system and calendar used by a thread. The current UI culture provides for culture-sensitive retrieval of resources in resource files.
+
+> [!IMPORTANT]
+> The and properties don't work reliably when used with any thread other than the current thread. An is thrown if a thread attempts to read or write these properties on a different thread.
+> We recommend that you use the and properties to retrieve and set the current culture.
+
+When a new thread is instantiated, its culture and UI culture are defined by the current system culture and UI culture, and not by the culture and UI culture of the thread from which the new thread is created. This means, for example, that if the current system culture is English (United States) and the current culture of the primary application thread is French (France), the culture of a new thread created by calling the constructor from the primary thread is English (United States), and not French (France). For more information, see the "Culture and threads" section of the class topic.
+
+> [!IMPORTANT]
+> This is not true of threads that execute asynchronous operations for apps that target .NET Framework 4.6 and later versions. In this case, the culture and UI culture is part of an asynchronous operation's context; the thread on which an asynchronous operation executes by default inherits the culture and UI culture of the thread from which the asynchronous operation was launched. For more information, see the "Culture and task-based asynchronous operations" section of the class remarks.
+
+You can do either of the following to ensure that all of the threads executing in an application share the same culture and UI culture:
+
+- You can pass a object that represents that culture to the delegate or the method.
+
+- For apps running on .NET Framework 4.5 and later versions, you can define the culture and UI culture that is to be assigned to all threads created in an application domain by setting the value of the and properties. Note that this is a per-application domain setting.
+
+For more information and examples, see the "Culture and threads" section of the class remarks.
+
+## Get information about and control threads
+
+You can retrieve a number of property values that provide information about a thread. In some cases, you can also set these property values to control the operation of the thread. These thread properties include:
+
+- A name. is a write-once property that you can use to identify a thread. Its default value is `null`.
+
+- A hash code, which you can retrieve by calling the method. The hash code can be used to uniquely identify a thread; for the lifetime of your thread, its hash code will not collide with the value from any other thread, regardless of the application domain from which you obtain the value.
+
+- A thread ID. The value of the read-only property is assigned by the runtime and uniquely identifies a thread within its process.
+
+ > [!NOTE]
+ > An operating-system [ThreadId](/windows/win32/api/processthreadsapi/nf-processthreadsapi-getthreadid) has no fixed relationship to a managed thread, because an unmanaged host can control the relationship between managed and unmanaged threads. Specifically, a sophisticated host can use the [CLR Hosting API](/dotnet/framework/unmanaged-api/hosting/index) to schedule many managed threads against the same operating system thread, or to move a managed thread between different operating system threads.
+
+- The thread's current state. For the duration of its existence, a thread is always in one or more of the states defined by the property.
+
+- A scheduling priority level, which is defined by the property. Although you can set this value to request a thread's priority, it is not guaranteed to be honored by the operating system.
+
+- The read-only property, which indicates whether a thread is a thread-pool thread.
+
+- The property. For more information, see the [Foreground and background threads](#foreground-and-background-threads) section.
+
+## Examples
+
+The following example demonstrates simple threading functionality.
+
+:::code language="csharp" source="~/snippets/csharp/System.Threading/Thread/Overview/source.cs" id="Snippet1":::
+:::code language="fsharp" source="~/snippets/fsharp/System.Threading/Thread/Overview/source.fs" id="Snippet1":::
+:::code language="vb" source="~/snippets/visualbasic/System.Threading/Thread/Overview/source.vb" id="Snippet1":::
+
+This code produces output similar to the following:
+
+```output
+[VB, C++, C#]
+Main thread: Start a second thread.
+Main thread: Do some work.
+ThreadProc: 0
+Main thread: Do some work.
+ThreadProc: 1
+Main thread: Do some work.
+ThreadProc: 2
+Main thread: Do some work.
+ThreadProc: 3
+Main thread: Call Join(), to wait until ThreadProc ends.
+ThreadProc: 4
+ThreadProc: 5
+ThreadProc: 6
+ThreadProc: 7
+ThreadProc: 8
+ThreadProc: 9
+Main thread: ThreadProc.Join has returned. Press Enter to end program.
+```
+
+ ]]>
+ This type is thread safe.Threads and ThreadingUsing Threads and Threading