1、FileUpload上传是时使用异步方式,但需要向调用方(另一线程)发布状态信息(例子里只有上传完毕状态,实际可以包括进度等状态),
调用方不想处理多线程问题,于是考虑SynchronizationContext
2、例子里调用方需要等待上传线程完成,于是用了EventWaitHandle,好像是找麻烦了,呵呵
Code
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5using System.Threading;
6
7namespace ConsoleApplication1
8{
9 /**//// <summary>
10 /// 不同线程子键同步调用的辅助类
11 /// </summary>
12 internal sealed class OrderedSynchronizationContext : SynchronizationContext
13 {
14 fields#region fields
15 private Queue<KeyValuePair<SendOrPostCallback, object>> pendingCallbacks = new Queue<KeyValuePair<SendOrPostCallback, object>>();
16 #endregion
17
18 functions#region functions
19 public override void Post(SendOrPostCallback d, object state)
20 {
21 lock (this.pendingCallbacks)
22 {
23 this.pendingCallbacks.Enqueue(new KeyValuePair<SendOrPostCallback, object>(d, state));
24 if (this.pendingCallbacks.Count == 1)
25 {
26 ThreadPool.QueueUserWorkItem(new WaitCallback(this.ProcessPendingCallbacks));
27 }
28 }
29 }
30
31 private void ProcessPendingCallbacks(object state)
32 {
33 KeyValuePair<SendOrPostCallback, object> pair = new KeyValuePair<SendOrPostCallback, object>();
34 bool flag = false;
35 do
36 {
37 lock (this.pendingCallbacks)
38 {
39 if (this.pendingCallbacks.Count <= 0)
40 {
41 break;
42 }
43 pair = this.pendingCallbacks.Dequeue();
44 }
45 pair.Key(pair.Value);
46 }
47 while (flag);
48 }
49 #endregion
50 }
51
52 public delegate void UploadCompletedEventHandler();
53
54 /**//// <summary>
55 /// 模拟异步文件上传
56 /// </summary>
57 class FileUpload
58 {
59 public event UploadCompletedEventHandler Uploaded;
60 private SynchronizationContext _syncContext;
61
62 EventWaitHandle _waitHandle;
63
64 public FileUpload(EventWaitHandle waitHandle)
65 {
66 this._syncContext = SynchronizationContext.Current ?? new OrderedSynchronizationContext();
67 this._waitHandle = waitHandle;
68 }
69
70 public void Upload()
71 {
72 Console.WriteLine("Upload.Begin");
73 //模拟异步
74 ThreadStart ts = new ThreadStart(DoUpload);
75 new Thread(ts).Start();
76 }
77
78 void DoUpload()
79 {
80 //模拟上传
81 for (int i = 0; i < 5; i++)
82 {
83 Thread.Sleep(400);
84 Console.WriteLine("uploading {0}", i);
85 }
86 Console.WriteLine("DoUpload.Completed");
87 if (Uploaded != null)
88 {
89 //调用外部事件
90 if (SynchronizationContext.Current == this._syncContext)
91 {
92 Uploaded();
93 }
94 else
95 {
96 _syncContext.Post(state =>
97 {
98 Uploaded();
99
100 if (_waitHandle != null)
101 {
102 _waitHandle.Set();
103 }
104 }, null);
105 }
106 }
107 }
108 }
109
110 class Program
111 {
112 static void Main(string[] args)
113 {
114 ManualResetEvent asyncEvent = new ManualResetEvent(false);
115 FileUpload upload = new FileUpload(asyncEvent);
116 upload.Uploaded += () =>
117 {
118 Console.WriteLine("上载事件触发!");
119 };
120 Console.WriteLine("开始调用上载");
121 upload.Upload();
122 Console.WriteLine("异步上载立即返回");
123
124 asyncEvent.WaitOne();
125 Console.WriteLine("上载完毕!");
126 }
127 }
128}
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5using System.Threading;
6
7namespace ConsoleApplication1
8{
9 /**//// <summary>
10 /// 不同线程子键同步调用的辅助类
11 /// </summary>
12 internal sealed class OrderedSynchronizationContext : SynchronizationContext
13 {
14 fields#region fields
15 private Queue<KeyValuePair<SendOrPostCallback, object>> pendingCallbacks = new Queue<KeyValuePair<SendOrPostCallback, object>>();
16 #endregion
17
18 functions#region functions
19 public override void Post(SendOrPostCallback d, object state)
20 {
21 lock (this.pendingCallbacks)
22 {
23 this.pendingCallbacks.Enqueue(new KeyValuePair<SendOrPostCallback, object>(d, state));
24 if (this.pendingCallbacks.Count == 1)
25 {
26 ThreadPool.QueueUserWorkItem(new WaitCallback(this.ProcessPendingCallbacks));
27 }
28 }
29 }
30
31 private void ProcessPendingCallbacks(object state)
32 {
33 KeyValuePair<SendOrPostCallback, object> pair = new KeyValuePair<SendOrPostCallback, object>();
34 bool flag = false;
35 do
36 {
37 lock (this.pendingCallbacks)
38 {
39 if (this.pendingCallbacks.Count <= 0)
40 {
41 break;
42 }
43 pair = this.pendingCallbacks.Dequeue();
44 }
45 pair.Key(pair.Value);
46 }
47 while (flag);
48 }
49 #endregion
50 }
51
52 public delegate void UploadCompletedEventHandler();
53
54 /**//// <summary>
55 /// 模拟异步文件上传
56 /// </summary>
57 class FileUpload
58 {
59 public event UploadCompletedEventHandler Uploaded;
60 private SynchronizationContext _syncContext;
61
62 EventWaitHandle _waitHandle;
63
64 public FileUpload(EventWaitHandle waitHandle)
65 {
66 this._syncContext = SynchronizationContext.Current ?? new OrderedSynchronizationContext();
67 this._waitHandle = waitHandle;
68 }
69
70 public void Upload()
71 {
72 Console.WriteLine("Upload.Begin");
73 //模拟异步
74 ThreadStart ts = new ThreadStart(DoUpload);
75 new Thread(ts).Start();
76 }
77
78 void DoUpload()
79 {
80 //模拟上传
81 for (int i = 0; i < 5; i++)
82 {
83 Thread.Sleep(400);
84 Console.WriteLine("uploading {0}", i);
85 }
86 Console.WriteLine("DoUpload.Completed");
87 if (Uploaded != null)
88 {
89 //调用外部事件
90 if (SynchronizationContext.Current == this._syncContext)
91 {
92 Uploaded();
93 }
94 else
95 {
96 _syncContext.Post(state =>
97 {
98 Uploaded();
99
100 if (_waitHandle != null)
101 {
102 _waitHandle.Set();
103 }
104 }, null);
105 }
106 }
107 }
108 }
109
110 class Program
111 {
112 static void Main(string[] args)
113 {
114 ManualResetEvent asyncEvent = new ManualResetEvent(false);
115 FileUpload upload = new FileUpload(asyncEvent);
116 upload.Uploaded += () =>
117 {
118 Console.WriteLine("上载事件触发!");
119 };
120 Console.WriteLine("开始调用上载");
121 upload.Upload();
122 Console.WriteLine("异步上载立即返回");
123
124 asyncEvent.WaitOne();
125 Console.WriteLine("上载完毕!");
126 }
127 }
128}
结果:
开始调用上载
Upload.Begin...
异步上载立即返回
uploading 0...
uploading 1...
uploading 2...
uploading 3...
uploading 4...
DoUpload.Completed
上载事件触发!
上载完毕!