QueueUserWorkItem方法将非常简单的任务排入队列
下面这个简单的代码,涉及到资源竞争问题,如果主线程先争取到资源,如果没有等待
一段时间,那么QueueUserWorkItem申请的线程没有机会执行。
1 using System;
2 using System.Threading;
3
4 public static void Main()
5 {
6 // Queue the task.
7 ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadProc));
8
9 Console.WriteLine("Main thread does some work, then sleeps.");
10 // If you comment out the Sleep, the main thread exits before
11 // the thread pool task runs. The thread pool uses background
12 // threads, which do not keep the application running. (This
13 // is a simple example of a race condition.)
14 Thread.Sleep(1000);
15
16 Console.WriteLine("Main thread exits.");
17 }
18
19 // This thread procedure performs the task.
20 static void ThreadProc(Object stateInfo)
21 {
22 // No state object was passed to QueueUserWorkItem, so
23 // stateInfo is null.
24 Console.WriteLine("Hello from the thread pool.");
25 }
26
下面的代码示例使用 QueueUserWorkItem 方法将任务排入队列,并为该任务提供数据。
1 using System;
2 using System.Threading;
3
4 // TaskInfo holds state information for a task that will be
5 // executed by a ThreadPool thread.
6 public class TaskInfo
7 {
8 // State information for the task. These members
9 // can be implemented as read-only properties, read/write
10 // properties with validation, and so on, as required.
11 public string Boilerplate;
12 public int Value;
13
14 // Public constructor provides an easy way to supply all
15 // the information needed for the task.
16 public TaskInfo(string text, int number)
17 {
18 Boilerplate = text;
19 Value = number;
20 }
21 }
22
23 public class Example
24 {
25 public static void Main()
26 {
27 // Create an object containing the information needed
28 // for the task.
29 TaskInfo ti = new TaskInfo("This report displays the number {0}.", 42);
30
31 // Queue the task and data.
32 if (ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadProc), ti))
33 {
34 Console.WriteLine("Main thread does some work, then sleeps.");
35
36 // If you comment out the Sleep, the main thread exits before
37 // the ThreadPool task has a chance to run. ThreadPool uses
38 // background threads, which do not keep the application
39 // running. (This is a simple example of a race condition.)
40 Thread.Sleep(1000);
41
42 Console.WriteLine("Main thread exits.");
43 }
44 else
45 {
46 Console.WriteLine("Unable to queue ThreadPool request.");
47 }
48 }
49
50 // The thread procedure performs the independent task, in this case
51 // formatting and printing a very simple report.
52 //
53 static void ThreadProc(Object stateInfo)
54 {
55 TaskInfo ti = (TaskInfo)stateInfo;
56 Console.WriteLine(ti.Boilerplate, ti.Value);
57 }
58 }
59
使用 RegisterWaitForSingleObject
下面的示例展示多种线程处理功能。
-
使用 RegisterWaitForSingleObject 方法,将任务排入队列,以便由 ThreadPool 线程执行。
-
使用 AutoResetEvent 发出要执行的任务的信号。 请参阅 EventWaitHandle, AutoResetEvent, CountdownEvent, ManualResetEvent。
-
使用 WaitOrTimerCallback 委托处理超时和信号。
使用 RegisteredWaitHandle 取消排队的任务。
注意:
在Main方法的最后有一句:
If you start a thread yourself, you can wait for it to end by calling Thread.Join. This option is not available with thread pool threads.
1 using System;
2 using System.Threading;
3
4 // TaskInfo contains data that will be passed to the callback
5 // method.
6 public class TaskInfo
7 {
8 public RegisteredWaitHandle Handle = null;
9 public string OtherInfo = "default";
10 }
11
12 public class Example
13 {
14 public static void Main(string[] args)
15 {
16 // The main thread uses AutoResetEvent to signal the
17 // registered wait handle, which executes the callback
18 // method.
19 AutoResetEvent ev = new AutoResetEvent(false);
20
21 TaskInfo ti = new TaskInfo();
22 ti.OtherInfo = "First task";
23 // The TaskInfo for the task includes the registered wait
24 // handle returned by RegisterWaitForSingleObject. This
25 // allows the wait to be terminated when the object has
26 // been signaled once (see WaitProc).
27 ti.Handle = ThreadPool.RegisterWaitForSingleObject(
28 ev,
29 new WaitOrTimerCallback(WaitProc),
30 ti,
31 1000,
32 false);
33
34 // The main thread waits three seconds, to demonstrate the
35 // time-outs on the queued thread, and then signals.
36 Thread.Sleep(3100);
37 Console.WriteLine("Main thread signals.");
38 ev.Set();
39
40 // The main thread sleeps, which should give the callback
41 // method time to execute. If you comment out this line, the
42 // program usually ends before the ThreadPool thread can execute.
43 Thread.Sleep(1000);
44 // If you start a thread yourself, you can wait for it to end
45 // by calling Thread.Join. This option is not available with
46 // thread pool threads.
47 }
48
49 // The callback method executes when the registered wait times out,
50 // or when the WaitHandle (in this case AutoResetEvent) is signaled.
51 // WaitProc unregisters the WaitHandle the first time the event is
52 // signaled.
53 public static void WaitProc(object state, bool timedOut)
54 {
55 // The state object must be cast to the correct type, because the
56 // signature of the WaitOrTimerCallback delegate specifies type
57 // Object.
58 TaskInfo ti = (TaskInfo)state;
59
60 string cause = "TIMED OUT";
61 if (!timedOut)
62 {
63 cause = "SIGNALED";
64 // If the callback method executes because the WaitHandle is
65 // signaled, stop future execution of the callback method
66 // by unregistering the WaitHandle.
67 if (ti.Handle != null)
68 ti.Handle.Unregister(null);
69 }
70
71 Console.WriteLine("WaitProc( {0} ) executes on thread {1}; cause = {2}.",
72 ti.OtherInfo,
73 Thread.CurrentThread.GetHashCode().ToString(),
74 cause
75 );
76 }
77 }
78