Here I have code that provides some explanations to the multithreading in .NET. Wrote it to refresh what I know on concurrency.
1 /********************************************************
2 *
3 * CODE IS MY PRESENTATION
4 *
5 ********************************************************/
6 using System;
7 using System.IO;
8
9 //1. CLR threading is based on Windows threading.
10 //2. CLR threading is going away from correspondence with Windows threading.
11 //SO do not use native windows functions if you already writing CLR code
12 //that is for future, of course Microsoft is not sleeping
13
14 //Let’s start
15 //This is namespace where Multithreading lives…
16 using System.Threading;
17
18 namespace TheoryConsole
19 {
20 class Program
21 {
22 static void Main(string[] args)
23 {
24 MultiThreadingInCLR presentation = new MultiThreadingInCLR();
25
26 //presentation.CLRHasPoolOfThreads();
27 //presentation.UsingThreadPoolForAsynchCalculations();
28 //presentation.UsingDedicatedThread();
29 //presentation.PeriodicalCallinOfAsynchOperations();
30 presentation.AsynchronousProgrammingModel();
31
32 Thread.Sleep(100);
33 //Console.WriteLine(“Press any key to exit…”);
34 //Console.ReadLine();
35 }
36 }
37
38 public class MultiThreadingInCLR
39 {
40 //Many developers uses multithreading too often,
41 //but it is not cheap.
42
43 //Because
44 //to Switch context system needs:
45 // – go to core -> save processor registers ->
46 // put spin-blocker -> take another thread ->
47 // unput blocker -> load registers > run thread
48
49 //Pool of Threads
50 public void CLRHasPoolOfThreads()
51 {
52 //Each Process has its oun Pool wich can be used
53 // in all AppDomains of that Process
54 ThreadPool.QueueUserWorkItem(DoAsynchWork, 10);
55
56 //If there are no requests to Pool,
57 //CLR will delete threads from it in about 2 minutes
58
59 // Amount of threads in Pool
60 // – Do not try to limit amount of threads in Pool
61 // There are two types of threads: Worker and I/O
62 int workingThreads = 0;
63 int completionThreads = 0;
64 //Get/Set Max/Min Threads
65 ThreadPool.GetMaxThreads(out workingThreads, out completionThreads);
66
67 //To GetAvailableThreads call it:
68 //ThreadPool.GetAvailableThreads();
69
70 for (int i = 0; i < 506; i++)
71 {
72 ThreadPool.QueueUserWorkItem(DoAsynchWork, 100);
73 }
74
75 ThreadPool.GetMaxThreads(out workingThreads, out completionThreads);
76 workingThreads = 1000;
77 }
78
79
80 public void UsingThreadPoolForAsynchCalculations()
81 {
82 //If you do not need I/O operations use Worker type of thread
83 //For example spell-checker in some editor need to work asynchronously
84 //
85 //Most commonly these three methods are called:
86 //
87 //static Boolean QueueUserWorkItem(WaitCallback callBack);
88 //static Boolean
89 // QueueUserWorkItem(WaitCallback callBack, Object state);
90 //static Boolean
91 // UnsafeQueueUserWorkItem(WaitCallback callBack, Object state);
92
93 //callBack is delegate with the next signature:
94 //delegate void WaitCallBack(Object state);
95 WaitCallBackExample_IDoHardWork(null);
96
97 //Here is how to start doing hard work asynchromously
98 ThreadPool.QueueUserWorkItem(WaitCallBackExample_IDoHardWork);
99
100 //Use UnsafeQueueUserWorkItem if the time resource is very critical
101 //Reason: QueueUserWorkItem is verifying
102 // if the assemblies from Thread stack has permissions
103 // to access file for example
104 //SecurityException could be generated if there is no presmissions
105 }
106
107 #region Dedicated Thread
108 public void UsingDedicatedThread()
109 {
110 //Commonly is used if we need to set some priority to thread
111 // or if we need to change other properties of Thread
112 // – we need set some properties to the thread
113 // – we need set priority to our thread
114 // (ThreadPool has one priority for all threads in it)
115 // – if we want run Thread in foreground
116 // (ThreadPoole runs threads in background)
117
118 //please note that here we do NOT create actual thread,
119 // because thread will be created only
120 //when we will call our thread object
121 Thread someNewThread = new Thread(ComputeBoundWork);
122 //When we call Start method actuall thread is created
123 // and process starts
124
125 someNewThread.Start(1);
126 Thread.Sleep(1000);//this imitates some work in main thread
127
128 //Please note!
129 // that after ComputeBoundWork finished its work,
130 // actual system thread was deleted
131
132 // this waits while the dedicated thread will finish all its work…
133 someNewThread.Join();
134
135 // so this is some kind of sysnch of threads..
136 }
137 #endregion
138
139 #region Timer
140 public void PeriodicalCallinOfAsynchOperations()
141 {
142 //System.Threading namespace has Timer defined
143 //it has 4 very similar constructors
144 //this used only TimerCallback
145 //Timer timer1 = new Timer(ComputeBoundWork);
146 Timer timer2 = new Timer(ComputeBoundWork, null, 0, 1000);
147 // method will be called only once
148 //Timer timer3 =
149 // new Timer(ComputeBoundWork, null, 0, Timeout.Infinite);
150
151 //if you want to change timing behaviour of the timer
152 // you could use Change() method, or Dispose() to stop…
153 Thread.Sleep(10000);// this imitates some work here – 10 seconds
154 timer2.Dispose();
155
156 // Please note that there are 3 different Timers in FCL
157 // – System.Threading.Timer
158 // is most suitable for doing asynch operations
159 // – System.Windows.Forms.Timer
160 // is equivalent to WinAPI SetTimer.. events are added WM_TIMER
161 // – System.Timers.Timer
162 // is some kind of wrapper of the Threading.Timer
163 }
164 #endregion
165
166 #region Asynchronous Programming Model
167
168 private IAsyncResult synchResultForFileWriting;
169 private FileStream fs;
170 public void AsynchronousProgrammingModel()
171 {
172 // Using of the asynchronous operations is the key to big programms :)
173 // Combination of it with the ThreadPool
174 // is way to effectively use all processors of the system.
175 // Examples where it is used…
176 // – System.IO.Stream -> FileStream and NetworkStream
177 // derived classes has methods BeginRead(), BeginWrite()
178 // – System.Net.Dns -> BeginGetHostAddresses(),
179 // BeginGetHostByName(), and so on…
180 // – System.Net.Sockets -> BeginAccept(), BeginConnect(), …
181 // all delegate types has BeginInvoke(), what could be used in APM
182
183 //ok let we see file reading example
184 fs = new FileStream(
185 “test.bin”, FileMode.OpenOrCreate,
186 FileAccess.Write, FileShare.None, 35000, FileOptions.Asynchronous);
187 synchResultForFileWriting =
188 fs.BeginWrite(new byte[32738], 0, 32000, CallBackMethod, null);
189 Console.WriteLine(
190 “This is called just after we said to write something to file.”);
191
192
193 // There are 3 types of joining threads.. im APM
194 // 1. Waiting for finish of work
195 //Int32 readMeFile.EndRead(IAsyncResutl asyncResult)
196
197 // 2. Regualar polling – is not effective method
198 Stream readMeFile = new FileStream(“film.mp4”, FileMode.Open,
199 FileAccess.Read, FileShare.Read, 1024, FileOptions.Asynchronous);
200
201 byte[] fileContent = new byte[450000000];
202 IAsyncResult ar =
203 readMeFile.BeginRead
204 (fileContent, 0, fileContent.Length, null, null);
205
206 while (!ar.IsCompleted)
207 {
208 Console.WriteLine(
209 “Reading Large Music file operation is not completed…”);
210 Thread.Sleep(100);
211 }
212
213 //please note that this will not stop actuall
214 // thread because we were asking for finish above
215 readMeFile.EndRead(ar);
216 Console.WriteLine(“We already finished reading large music file.”);
217
218 // 3. Callback!!
219 // is the most efficient and commonly used joining type
220 }
221
222 private void UserAlreadyWantsToReadThatFile()
223 {
224 fs.EndWrite(synchResultForFileWriting);
225 //now we are sure that ansynch writing to file has finished its work!!
226 fs.Close();
227 }
228
229
230 private void CallBackMethod(IAsyncResult ar)
231 {
232 //this method will be called when writing to file will finish its work
233 Console.WriteLine(“We just finished writing to file…”);
234 }
235
236 #endregion
237
238 public void WaitCallBackExample_IDoHardWork(object hardParameter)
239 {
240 //actually if you see my body you know that I do not do work
241 // I sleep for 2 seconds :)
242 Thread.Sleep(2000);
243 }
244
245 public void DoAsynchWork(object miliseconds)
246 {
247 Thread.Sleep((int)miliseconds);
248 }
249
250 public void ComputeBoundWork(object opCode)
251 {
252 Thread.Sleep(1000);// this imitates some work…
253 Console.WriteLine(
254 string.Format(“Compuing bound work with param: {0}”, opCode));
255 }
256 }
257 }
code
more code
~~~~