aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/ThirdParty/SmartThreadPool/Interfaces.cs
diff options
context:
space:
mode:
Diffstat (limited to 'ThirdParty/SmartThreadPool/Interfaces.cs')
-rw-r--r--ThirdParty/SmartThreadPool/Interfaces.cs628
1 files changed, 628 insertions, 0 deletions
diff --git a/ThirdParty/SmartThreadPool/Interfaces.cs b/ThirdParty/SmartThreadPool/Interfaces.cs
new file mode 100644
index 0000000..8cc23a0
--- /dev/null
+++ b/ThirdParty/SmartThreadPool/Interfaces.cs
@@ -0,0 +1,628 @@
1using System;
2using System.Threading;
3
4namespace Amib.Threading
5{
6 #region Delegates
7
8 /// <summary>
9 /// A delegate that represents the method to run as the work item
10 /// </summary>
11 /// <param name="state">A state object for the method to run</param>
12 public delegate object WorkItemCallback(object state);
13
14 /// <summary>
15 /// A delegate to call after the WorkItemCallback completed
16 /// </summary>
17 /// <param name="wir">The work item result object</param>
18 public delegate void PostExecuteWorkItemCallback(IWorkItemResult wir);
19
20 /// <summary>
21 /// A delegate to call after the WorkItemCallback completed
22 /// </summary>
23 /// <param name="wir">The work item result object</param>
24 public delegate void PostExecuteWorkItemCallback<TResult>(IWorkItemResult<TResult> wir);
25
26 /// <summary>
27 /// A delegate to call when a WorkItemsGroup becomes idle
28 /// </summary>
29 /// <param name="workItemsGroup">A reference to the WorkItemsGroup that became idle</param>
30 public delegate void WorkItemsGroupIdleHandler(IWorkItemsGroup workItemsGroup);
31
32 /// <summary>
33 /// A delegate to call after a thread is created, but before
34 /// it's first use.
35 /// </summary>
36 public delegate void ThreadInitializationHandler();
37
38 /// <summary>
39 /// A delegate to call when a thread is about to exit, after
40 /// it is no longer belong to the pool.
41 /// </summary>
42 public delegate void ThreadTerminationHandler();
43
44 #endregion
45
46 #region WorkItem Priority
47
48 /// <summary>
49 /// Defines the availeable priorities of a work item.
50 /// The higher the priority a work item has, the sooner
51 /// it will be executed.
52 /// </summary>
53 public enum WorkItemPriority
54 {
55 Lowest,
56 BelowNormal,
57 Normal,
58 AboveNormal,
59 Highest,
60 }
61
62 #endregion
63
64 #region IWorkItemsGroup interface
65
66 /// <summary>
67 /// IWorkItemsGroup interface
68 /// Created by SmartThreadPool.CreateWorkItemsGroup()
69 /// </summary>
70 public interface IWorkItemsGroup
71 {
72 /// <summary>
73 /// Get/Set the name of the WorkItemsGroup
74 /// </summary>
75 string Name { get; set; }
76
77 /// <summary>
78 /// Get/Set the maximum number of workitem that execute cocurrency on the thread pool
79 /// </summary>
80 int Concurrency { get; set; }
81
82 /// <summary>
83 /// Get the number of work items waiting in the queue.
84 /// </summary>
85 int WaitingCallbacks { get; }
86
87 /// <summary>
88 /// Get an array with all the state objects of the currently running items.
89 /// The array represents a snap shot and impact performance.
90 /// </summary>
91 object[] GetStates();
92
93 /// <summary>
94 /// Get the WorkItemsGroup start information
95 /// </summary>
96 WIGStartInfo WIGStartInfo { get; }
97
98 /// <summary>
99 /// Starts to execute work items
100 /// </summary>
101 void Start();
102
103 /// <summary>
104 /// Cancel all the work items.
105 /// Same as Cancel(false)
106 /// </summary>
107 void Cancel();
108
109 /// <summary>
110 /// Cancel all work items using thread abortion
111 /// </summary>
112 /// <param name="abortExecution">True to stop work items by raising ThreadAbortException</param>
113 void Cancel(bool abortExecution);
114
115 /// <summary>
116 /// Wait for all work item to complete.
117 /// </summary>
118 void WaitForIdle();
119
120 /// <summary>
121 /// Wait for all work item to complete, until timeout expired
122 /// </summary>
123 /// <param name="timeout">How long to wait for the work items to complete</param>
124 /// <returns>Returns true if work items completed within the timeout, otherwise false.</returns>
125 bool WaitForIdle(TimeSpan timeout);
126
127 /// <summary>
128 /// Wait for all work item to complete, until timeout expired
129 /// </summary>
130 /// <param name="millisecondsTimeout">How long to wait for the work items to complete in milliseconds</param>
131 /// <returns>Returns true if work items completed within the timeout, otherwise false.</returns>
132 bool WaitForIdle(int millisecondsTimeout);
133
134 /// <summary>
135 /// IsIdle is true when there are no work items running or queued.
136 /// </summary>
137 bool IsIdle { get; }
138
139 /// <summary>
140 /// This event is fired when all work items are completed.
141 /// (When IsIdle changes to true)
142 /// This event only work on WorkItemsGroup. On SmartThreadPool
143 /// it throws the NotImplementedException.
144 /// </summary>
145 event WorkItemsGroupIdleHandler OnIdle;
146
147 #region QueueWorkItem
148
149 /// <summary>
150 /// Queue a work item
151 /// </summary>
152 /// <param name="callback">A callback to execute</param>
153 /// <returns>Returns a work item result</returns>
154 IWorkItemResult QueueWorkItem(WorkItemCallback callback);
155
156 /// <summary>
157 /// Queue a work item
158 /// </summary>
159 /// <param name="callback">A callback to execute</param>
160 /// <param name="workItemPriority">The priority of the work item</param>
161 /// <returns>Returns a work item result</returns>
162 IWorkItemResult QueueWorkItem(WorkItemCallback callback, WorkItemPriority workItemPriority);
163
164 /// <summary>
165 /// Queue a work item
166 /// </summary>
167 /// <param name="callback">A callback to execute</param>
168 /// <param name="state">
169 /// The context object of the work item. Used for passing arguments to the work item.
170 /// </param>
171 /// <returns>Returns a work item result</returns>
172 IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state);
173
174 /// <summary>
175 /// Queue a work item
176 /// </summary>
177 /// <param name="callback">A callback to execute</param>
178 /// <param name="state">
179 /// The context object of the work item. Used for passing arguments to the work item.
180 /// </param>
181 /// <param name="workItemPriority">The work item priority</param>
182 /// <returns>Returns a work item result</returns>
183 IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, WorkItemPriority workItemPriority);
184
185 /// <summary>
186 /// Queue a work item
187 /// </summary>
188 /// <param name="callback">A callback to execute</param>
189 /// <param name="state">
190 /// The context object of the work item. Used for passing arguments to the work item.
191 /// </param>
192 /// <param name="postExecuteWorkItemCallback">
193 /// A delegate to call after the callback completion
194 /// </param>
195 /// <returns>Returns a work item result</returns>
196 IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, PostExecuteWorkItemCallback postExecuteWorkItemCallback);
197
198 /// <summary>
199 /// Queue a work item
200 /// </summary>
201 /// <param name="callback">A callback to execute</param>
202 /// <param name="state">
203 /// The context object of the work item. Used for passing arguments to the work item.
204 /// </param>
205 /// <param name="postExecuteWorkItemCallback">
206 /// A delegate to call after the callback completion
207 /// </param>
208 /// <param name="workItemPriority">The work item priority</param>
209 /// <returns>Returns a work item result</returns>
210 IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, PostExecuteWorkItemCallback postExecuteWorkItemCallback, WorkItemPriority workItemPriority);
211
212 /// <summary>
213 /// Queue a work item
214 /// </summary>
215 /// <param name="callback">A callback to execute</param>
216 /// <param name="state">
217 /// The context object of the work item. Used for passing arguments to the work item.
218 /// </param>
219 /// <param name="postExecuteWorkItemCallback">
220 /// A delegate to call after the callback completion
221 /// </param>
222 /// <param name="callToPostExecute">Indicates on which cases to call to the post execute callback</param>
223 /// <returns>Returns a work item result</returns>
224 IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, PostExecuteWorkItemCallback postExecuteWorkItemCallback, CallToPostExecute callToPostExecute);
225
226 /// <summary>
227 /// Queue a work item
228 /// </summary>
229 /// <param name="callback">A callback to execute</param>
230 /// <param name="state">
231 /// The context object of the work item. Used for passing arguments to the work item.
232 /// </param>
233 /// <param name="postExecuteWorkItemCallback">
234 /// A delegate to call after the callback completion
235 /// </param>
236 /// <param name="callToPostExecute">Indicates on which cases to call to the post execute callback</param>
237 /// <param name="workItemPriority">The work item priority</param>
238 /// <returns>Returns a work item result</returns>
239 IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, PostExecuteWorkItemCallback postExecuteWorkItemCallback, CallToPostExecute callToPostExecute, WorkItemPriority workItemPriority);
240
241 /// <summary>
242 /// Queue a work item
243 /// </summary>
244 /// <param name="workItemInfo">Work item info</param>
245 /// <param name="callback">A callback to execute</param>
246 /// <returns>Returns a work item result</returns>
247 IWorkItemResult QueueWorkItem(WorkItemInfo workItemInfo, WorkItemCallback callback);
248
249 /// <summary>
250 /// Queue a work item
251 /// </summary>
252 /// <param name="workItemInfo">Work item information</param>
253 /// <param name="callback">A callback to execute</param>
254 /// <param name="state">
255 /// The context object of the work item. Used for passing arguments to the work item.
256 /// </param>
257 /// <returns>Returns a work item result</returns>
258 IWorkItemResult QueueWorkItem(WorkItemInfo workItemInfo, WorkItemCallback callback, object state);
259
260 #endregion
261
262 #region QueueWorkItem(Action<...>)
263
264 /// <summary>
265 /// Queue a work item.
266 /// </summary>
267 /// <returns>Returns a IWorkItemResult object, but its GetResult() will always return null</returns>
268 IWorkItemResult QueueWorkItem(Action action);
269
270 /// <summary>
271 /// Queue a work item.
272 /// </summary>
273 /// <returns>Returns a IWorkItemResult object, but its GetResult() will always return null</returns>
274 IWorkItemResult QueueWorkItem (Action action, WorkItemPriority priority);
275
276 /// <summary>
277 /// Queue a work item.
278 /// </summary>
279 /// <returns>Returns a IWorkItemResult object, but its GetResult() will always return null</returns>
280 IWorkItemResult QueueWorkItem<T> (Action<T> action, T arg, WorkItemPriority priority);
281
282 /// <summary>
283 /// Queue a work item.
284 /// </summary>
285 /// <returns>Returns a IWorkItemResult object, but its GetResult() will always return null</returns>
286 IWorkItemResult QueueWorkItem<T> (Action<T> action, T arg);
287
288 /// <summary>
289 /// Queue a work item.
290 /// </summary>
291 /// <returns>Returns a IWorkItemResult object, but its GetResult() will always return null</returns>
292 IWorkItemResult QueueWorkItem<T1, T2>(Action<T1, T2> action, T1 arg1, T2 arg2);
293
294 /// <summary>
295 /// Queue a work item.
296 /// </summary>
297 /// <returns>Returns a IWorkItemResult object, but its GetResult() will always return null</returns>
298 IWorkItemResult QueueWorkItem<T1, T2> (Action<T1, T2> action, T1 arg1, T2 arg2, WorkItemPriority priority);
299
300 /// <summary>
301 /// Queue a work item.
302 /// </summary>
303 /// <returns>Returns a IWorkItemResult object, but its GetResult() will always return null</returns>
304 IWorkItemResult QueueWorkItem<T1, T2, T3>(Action<T1, T2, T3> action, T1 arg1, T2 arg2, T3 arg3);
305
306 /// <summary>
307 /// Queue a work item.
308 /// </summary>
309 /// <returns>Returns a IWorkItemResult object, but its GetResult() will always return null</returns>
310 IWorkItemResult QueueWorkItem<T1, T2, T3> (Action<T1, T2, T3> action, T1 arg1, T2 arg2, T3 arg3, WorkItemPriority priority);
311
312 /// <summary>
313 /// Queue a work item.
314 /// </summary>
315 /// <returns>Returns a IWorkItemResult object, but its GetResult() will always return null</returns>
316 IWorkItemResult QueueWorkItem<T1, T2, T3, T4>(Action<T1, T2, T3, T4> action, T1 arg1, T2 arg2, T3 arg3, T4 arg4);
317
318 /// <summary>
319 /// Queue a work item.
320 /// </summary>
321 /// <returns>Returns a IWorkItemResult object, but its GetResult() will always return null</returns>
322 IWorkItemResult QueueWorkItem<T1, T2, T3, T4> (Action<T1, T2, T3, T4> action, T1 arg1, T2 arg2, T3 arg3, T4 arg4, WorkItemPriority priority);
323
324 #endregion
325
326 #region QueueWorkItem(Func<...>)
327
328 /// <summary>
329 /// Queue a work item.
330 /// </summary>
331 /// <returns>Returns a IWorkItemResult&lt;TResult&gt; object.
332 /// its GetResult() returns a TResult object</returns>
333 IWorkItemResult<TResult> QueueWorkItem<TResult>(Func<TResult> func);
334
335 /// <summary>
336 /// Queue a work item.
337 /// </summary>
338 /// <returns>Returns a IWorkItemResult&lt;TResult&gt; object.
339 /// its GetResult() returns a TResult object</returns>
340 IWorkItemResult<TResult> QueueWorkItem<T, TResult>(Func<T, TResult> func, T arg);
341
342 /// <summary>
343 /// Queue a work item.
344 /// </summary>
345 /// <returns>Returns a IWorkItemResult&lt;TResult&gt; object.
346 /// its GetResult() returns a TResult object</returns>
347 IWorkItemResult<TResult> QueueWorkItem<T1, T2, TResult>(Func<T1, T2, TResult> func, T1 arg1, T2 arg2);
348
349 /// <summary>
350 /// Queue a work item.
351 /// </summary>
352 /// <returns>Returns a IWorkItemResult&lt;TResult&gt; object.
353 /// its GetResult() returns a TResult object</returns>
354 IWorkItemResult<TResult> QueueWorkItem<T1, T2, T3, TResult>(Func<T1, T2, T3, TResult> func, T1 arg1, T2 arg2, T3 arg3);
355
356 /// <summary>
357 /// Queue a work item.
358 /// </summary>
359 /// <returns>Returns a IWorkItemResult&lt;TResult&gt; object.
360 /// its GetResult() returns a TResult object</returns>
361 IWorkItemResult<TResult> QueueWorkItem<T1, T2, T3, T4, TResult>(Func<T1, T2, T3, T4, TResult> func, T1 arg1, T2 arg2, T3 arg3, T4 arg4);
362
363 #endregion
364 }
365
366 #endregion
367
368 #region CallToPostExecute enumerator
369
370 [Flags]
371 public enum CallToPostExecute
372 {
373 /// <summary>
374 /// Never call to the PostExecute call back
375 /// </summary>
376 Never = 0x00,
377
378 /// <summary>
379 /// Call to the PostExecute only when the work item is cancelled
380 /// </summary>
381 WhenWorkItemCanceled = 0x01,
382
383 /// <summary>
384 /// Call to the PostExecute only when the work item is not cancelled
385 /// </summary>
386 WhenWorkItemNotCanceled = 0x02,
387
388 /// <summary>
389 /// Always call to the PostExecute
390 /// </summary>
391 Always = WhenWorkItemCanceled | WhenWorkItemNotCanceled,
392 }
393
394 #endregion
395
396 #region IWorkItemResult interface
397
398 /// <summary>
399 /// The common interface of IWorkItemResult and IWorkItemResult&lt;T&gt;
400 /// </summary>
401 public interface IWaitableResult
402 {
403 /// <summary>
404 /// This method intent is for internal use.
405 /// </summary>
406 /// <returns></returns>
407 IWorkItemResult GetWorkItemResult();
408
409 /// <summary>
410 /// This method intent is for internal use.
411 /// </summary>
412 /// <returns></returns>
413 IWorkItemResult<TResult> GetWorkItemResultT<TResult>();
414 }
415
416 /// <summary>
417 /// IWorkItemResult interface.
418 /// Created when a WorkItemCallback work item is queued.
419 /// </summary>
420 public interface IWorkItemResult : IWorkItemResult<object>
421 {
422 }
423
424 /// <summary>
425 /// IWorkItemResult&lt;TResult&gt; interface.
426 /// Created when a Func&lt;TResult&gt; work item is queued.
427 /// </summary>
428 public interface IWorkItemResult<TResult> : IWaitableResult
429 {
430 /// <summary>
431 /// Get the result of the work item.
432 /// If the work item didn't run yet then the caller waits.
433 /// </summary>
434 /// <returns>The result of the work item</returns>
435 TResult GetResult();
436
437 /// <summary>
438 /// Get the result of the work item.
439 /// If the work item didn't run yet then the caller waits until timeout.
440 /// </summary>
441 /// <returns>The result of the work item</returns>
442 /// On timeout throws WorkItemTimeoutException
443 TResult GetResult(
444 int millisecondsTimeout,
445 bool exitContext);
446
447 /// <summary>
448 /// Get the result of the work item.
449 /// If the work item didn't run yet then the caller waits until timeout.
450 /// </summary>
451 /// <returns>The result of the work item</returns>
452 /// On timeout throws WorkItemTimeoutException
453 TResult GetResult(
454 TimeSpan timeout,
455 bool exitContext);
456
457 /// <summary>
458 /// Get the result of the work item.
459 /// If the work item didn't run yet then the caller waits until timeout or until the cancelWaitHandle is signaled.
460 /// </summary>
461 /// <param name="millisecondsTimeout">Timeout in milliseconds, or -1 for infinite</param>
462 /// <param name="exitContext">
463 /// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false.
464 /// </param>
465 /// <param name="cancelWaitHandle">A cancel wait handle to interrupt the blocking if needed</param>
466 /// <returns>The result of the work item</returns>
467 /// On timeout throws WorkItemTimeoutException
468 /// On cancel throws WorkItemCancelException
469 TResult GetResult(
470 int millisecondsTimeout,
471 bool exitContext,
472 WaitHandle cancelWaitHandle);
473
474 /// <summary>
475 /// Get the result of the work item.
476 /// If the work item didn't run yet then the caller waits until timeout or until the cancelWaitHandle is signaled.
477 /// </summary>
478 /// <returns>The result of the work item</returns>
479 /// On timeout throws WorkItemTimeoutException
480 /// On cancel throws WorkItemCancelException
481 TResult GetResult(
482 TimeSpan timeout,
483 bool exitContext,
484 WaitHandle cancelWaitHandle);
485
486 /// <summary>
487 /// Get the result of the work item.
488 /// If the work item didn't run yet then the caller waits.
489 /// </summary>
490 /// <param name="e">Filled with the exception if one was thrown</param>
491 /// <returns>The result of the work item</returns>
492 TResult GetResult(out Exception e);
493
494 /// <summary>
495 /// Get the result of the work item.
496 /// If the work item didn't run yet then the caller waits until timeout.
497 /// </summary>
498 /// <param name="millisecondsTimeout"></param>
499 /// <param name="exitContext"></param>
500 /// <param name="e">Filled with the exception if one was thrown</param>
501 /// <returns>The result of the work item</returns>
502 /// On timeout throws WorkItemTimeoutException
503 TResult GetResult(
504 int millisecondsTimeout,
505 bool exitContext,
506 out Exception e);
507
508 /// <summary>
509 /// Get the result of the work item.
510 /// If the work item didn't run yet then the caller waits until timeout.
511 /// </summary>
512 /// <param name="exitContext"></param>
513 /// <param name="e">Filled with the exception if one was thrown</param>
514 /// <param name="timeout"></param>
515 /// <returns>The result of the work item</returns>
516 /// On timeout throws WorkItemTimeoutException
517 TResult GetResult(
518 TimeSpan timeout,
519 bool exitContext,
520 out Exception e);
521
522 /// <summary>
523 /// Get the result of the work item.
524 /// If the work item didn't run yet then the caller waits until timeout or until the cancelWaitHandle is signaled.
525 /// </summary>
526 /// <param name="millisecondsTimeout">Timeout in milliseconds, or -1 for infinite</param>
527 /// <param name="exitContext">
528 /// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false.
529 /// </param>
530 /// <param name="cancelWaitHandle">A cancel wait handle to interrupt the blocking if needed</param>
531 /// <param name="e">Filled with the exception if one was thrown</param>
532 /// <returns>The result of the work item</returns>
533 /// On timeout throws WorkItemTimeoutException
534 /// On cancel throws WorkItemCancelException
535 TResult GetResult(
536 int millisecondsTimeout,
537 bool exitContext,
538 WaitHandle cancelWaitHandle,
539 out Exception e);
540
541 /// <summary>
542 /// Get the result of the work item.
543 /// If the work item didn't run yet then the caller waits until timeout or until the cancelWaitHandle is signaled.
544 /// </summary>
545 /// <returns>The result of the work item</returns>
546 /// <param name="cancelWaitHandle"></param>
547 /// <param name="e">Filled with the exception if one was thrown</param>
548 /// <param name="timeout"></param>
549 /// <param name="exitContext"></param>
550 /// On timeout throws WorkItemTimeoutException
551 /// On cancel throws WorkItemCancelException
552 TResult GetResult(
553 TimeSpan timeout,
554 bool exitContext,
555 WaitHandle cancelWaitHandle,
556 out Exception e);
557
558 /// <summary>
559 /// Gets an indication whether the asynchronous operation has completed.
560 /// </summary>
561 bool IsCompleted { get; }
562
563 /// <summary>
564 /// Gets an indication whether the asynchronous operation has been canceled.
565 /// </summary>
566 bool IsCanceled { get; }
567
568 /// <summary>
569 /// Gets the user-defined object that contains context data
570 /// for the work item method.
571 /// </summary>
572 object State { get; }
573
574 /// <summary>
575 /// Same as Cancel(false).
576 /// </summary>
577 bool Cancel();
578
579 /// <summary>
580 /// Cancel the work item execution.
581 /// If the work item is in the queue then it won't execute
582 /// If the work item is completed, it will remain completed
583 /// If the work item is in progress then the user can check the SmartThreadPool.IsWorkItemCanceled
584 /// property to check if the work item has been cancelled. If the abortExecution is set to true then
585 /// the Smart Thread Pool will send an AbortException to the running thread to stop the execution
586 /// of the work item. When an in progress work item is canceled its GetResult will throw WorkItemCancelException.
587 /// If the work item is already cancelled it will remain cancelled
588 /// </summary>
589 /// <param name="abortExecution">When true send an AbortException to the executing thread.</param>
590 /// <returns>Returns true if the work item was not completed, otherwise false.</returns>
591 bool Cancel(bool abortExecution);
592
593 /// <summary>
594 /// Get the work item's priority
595 /// </summary>
596 WorkItemPriority WorkItemPriority { get; }
597
598 /// <summary>
599 /// Return the result, same as GetResult()
600 /// </summary>
601 TResult Result { get; }
602
603 /// <summary>
604 /// Returns the exception if occured otherwise returns null.
605 /// </summary>
606 object Exception { get; }
607 }
608
609 #endregion
610
611 #region .NET 3.5
612
613 // All these delegate are built-in .NET 3.5
614 // Comment/Remove them when compiling to .NET 3.5 to avoid ambiguity.
615
616 public delegate void Action();
617 public delegate void Action<T1, T2>(T1 arg1, T2 arg2);
618 public delegate void Action<T1, T2, T3>(T1 arg1, T2 arg2, T3 arg3);
619 public delegate void Action<T1, T2, T3, T4>(T1 arg1, T2 arg2, T3 arg3, T4 arg4);
620
621 public delegate TResult Func<TResult>();
622 public delegate TResult Func<T, TResult>(T arg1);
623 public delegate TResult Func<T1, T2, TResult>(T1 arg1, T2 arg2);
624 public delegate TResult Func<T1, T2, T3, TResult>(T1 arg1, T2 arg2, T3 arg3);
625 public delegate TResult Func<T1, T2, T3, T4, TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4);
626
627 #endregion
628}