HTTPDOWNLOADER for updater application block for .Net2.0
updater application block for .Net2.0已经发布了,但是我使用了一下,因为是使用后台更新的缘故,所以速度特别慢。30M的东西差不多要花费30分钟,简直无法忍受,弄了个httpdownloader,在这里共享给大家。
你需要Enterprise Libary 2006
![](/Images/OutliningIndicators/ContractedBlock.gif)
HttpDownloader
1
using System;
2
using System.IO;
3
using System.Net;
4
using System.Threading;
5
using System.Security.Permissions;
6
using Microsoft.ApplicationBlocks.Updater;
7
using Microsoft.ApplicationBlocks.Updater.Configuration;
8
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
9
namespace x.HttpDownloader
10![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
11![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
12
/// Implements a HTTP downloader for the updater application block V2.0.
13
/// </summary>
14
/// <remarks>
15
/// The <c>HttpDownloader</c> class can be used to download application updates via HTTP. It supports synchronous and asynchronous
16
/// operation as well as progress reporting. In addition, the progress reporting is not at the file level, it is at the byte level.
17
/// </remarks>
18
[ConfigurationElementType(typeof(HttpDownloaderProviderData))]
19
public sealed class HttpDownloader : IDownloader
20![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
21![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
22
/// The thread to perform the download.
23
/// </summary>
24
private Thread _downloaderThread;
25![](/Images/OutliningIndicators/InBlock.gif)
26![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
27
/// Contains configuration settings for the HTTP downloader.
28
/// </summary>
29
//private HttpDownloaderProviderData _configuration;
30![](/Images/OutliningIndicators/InBlock.gif)
31![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
32
/// The configuration name for this downloader.
33
/// </summary>
34
private const string CONFIGURATION_NAME = "downloaders";
35![](/Images/OutliningIndicators/InBlock.gif)
36![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
37
/// The download provider name.
38
/// </summary>
39
private const string DOWNLOAD_PROVIDER_NAME = "HTTPDownloader";
40![](/Images/OutliningIndicators/InBlock.gif)
41![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
42
/// A synchronisation object.
43
/// </summary>
44
private readonly object LOCK = new object();
45![](/Images/OutliningIndicators/InBlock.gif)
46![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
47
/// Gets the configuration name for the HTTP downloader.
48
/// </summary>
49
public string ConfigurationName
50![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
51
get
52![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
53
return CONFIGURATION_NAME;
54
}
55
set
56![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
57
//nothing to do
58
}
59
}
60
61![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
62
/// Initialises the HTTP downloader.
63
/// </summary>
64
//public void Initialize(ConfigurationView configurationView)
65
//{
66
// UpdaterConfigurationView updaterConfigurationView = (UpdaterConfigurationView) configurationView;
67
// _configuration = (HttpDownloaderProviderData) updaterConfigurationView.GetDownloadProviderData(DOWNLOAD_PROVIDER_NAME);
68
//}
69![](/Images/OutliningIndicators/InBlock.gif)
70![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
71
/// Downloads the specified task synchronously via HTTP. If <paramref name="maxWaitTime"/> is surpassed prior to the download
72
/// completing, a download error is raised.
73
/// </summary>
74
[FileIOPermission(SecurityAction.Demand)]
75
public void Download(UpdaterTask task, TimeSpan maxWaitTime)
76![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
77
try
78![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
79
OnDownloadStarted(new TaskEventArgs(task));
80
//this object is used to perform the downloading on a separate thread
81
AsyncDownloader downloader = new AsyncDownloader(task, new OnDownloadProgressEventHandler(OnDownloadProgress), new OnDownloadTotalSizeCalculationStartedEventHandler(OnDownloadTotalSizeCalculationStarted), new OnDownloadTotalSizeCalculationProgressEventHandler(OnDownloadTotalSizeCalculationProgress), new OnDownloadTotalSizeCalculationCompletedEventHandler(OnDownloadTotalSizeCalculationCompleted), new OnDownloadCompletedEventHandler(OnDownloadCompleted));
82
CreateDownloaderThread(downloader);
83
_downloaderThread.Start();
84
//DateTime endTime = DateTime.Now + maxWaitTime;
85
double endTime = Environment.TickCount + maxWaitTime.TotalMilliseconds;
86
while ((endTime > Environment.TickCount) && !downloader.IsComplete)
87![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
88
Thread.Sleep(100);
89
}
90![](/Images/OutliningIndicators/InBlock.gif)
91
if (!downloader.IsComplete)
92![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
93
//abort the thread if it didn't complete
94
_downloaderThread.Abort();
95
throw new ApplicationUpdaterException("Download surpassed time out of " + maxWaitTime);
96
}
97
else if (downloader.Exception != null)
98![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
99
//raise the error event if the downloader thread erred out
100
OnDownloadError(new DownloadTaskErrorEventArgs(task, downloader.Exception));
101
}
102
}
103
catch (Exception e)
104![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
105
OnDownloadError(new DownloadTaskErrorEventArgs(task, e));
106
}
107
}
108![](/Images/OutliningIndicators/InBlock.gif)
109![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
110
/// Downloads the specified task asynchronously via HTTP.
111
/// </summary>
112
[FileIOPermission(SecurityAction.Demand)]
113
public void BeginDownload(UpdaterTask task)
114![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
115
try
116![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
117
OnDownloadStarted(new TaskEventArgs(task));
118
//this object is used to perform the downloading on a separate thread
119
AsyncDownloader downloader = new AsyncDownloader(task, new OnDownloadProgressEventHandler(OnDownloadProgress), new OnDownloadTotalSizeCalculationStartedEventHandler(OnDownloadTotalSizeCalculationStarted), new OnDownloadTotalSizeCalculationProgressEventHandler(OnDownloadTotalSizeCalculationProgress), new OnDownloadTotalSizeCalculationCompletedEventHandler(OnDownloadTotalSizeCalculationCompleted), new OnDownloadCompletedEventHandler(OnDownloadCompleted));
120
CreateDownloaderThread(downloader);
121
_downloaderThread.Start();
122
}
123
catch (Exception e)
124![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
125
OnDownloadError(new DownloadTaskErrorEventArgs(task, e));
126
}
127
}
128![](/Images/OutliningIndicators/InBlock.gif)
129![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
130
/// Cancels an asynchronous HTTP download operation.
131
/// </summary>
132
public bool CancelDownload(UpdaterTask task)
133![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
134
_downloaderThread.Abort();
135
return true;
136
}
137![](/Images/OutliningIndicators/InBlock.gif)
138![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
139
/// Creates the downloader thread.
140
/// </summary>
141
private void CreateDownloaderThread(AsyncDownloader downloader)
142![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
143
_downloaderThread = new Thread(new ThreadStart(downloader.Download));
144
_downloaderThread.Name = "Downloader";
145
_downloaderThread.IsBackground = true;
146
}
147![](/Images/OutliningIndicators/InBlock.gif)
148![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
149
/// Delegate for handling the <see cref="DownloadTotalSizeCalculationStarted"/> event.
150
/// </summary>
151
public delegate void DownloadTotalSizeCalculationStartedEventHandler(object sender, TaskEventArgs e);
152![](/Images/OutliningIndicators/InBlock.gif)
153![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
154
/// Delegate for handling the <see cref="DownloadTotalSizeCalculationCompleted"/> event.
155
/// </summary>
156
public delegate void DownloadTotalSizeCalculationProgressEventHandler(object sender, DownloadTotalSizeCalculationProgressEventArgs e);
157![](/Images/OutliningIndicators/InBlock.gif)
158![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
159
/// Delegate for handling the <see cref="DownloadTotalSizeCalculationCompleted"/> event.
160
/// </summary>
161
public delegate void DownloadTotalSizeCalculationCompletedEventHandler(object sender, TaskEventArgs e);
162![](/Images/OutliningIndicators/InBlock.gif)
163![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
164
/// Fired when the HTTP downloader begins calculating file sizes for the files to be downloaded.
165
/// </summary>
166
/// <remarks>
167
/// This event has to be <c>static</c> because the client is unable to obtain a reference to the <c>HttpDownloader</c> instance (updater design flaw).
168
/// </remarks>
169
public static event DownloadTotalSizeCalculationStartedEventHandler DownloadTotalSizeCalculationStarted;
170![](/Images/OutliningIndicators/InBlock.gif)
171![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
172
/// Fired when the HTTP downloader has progress information for file size calculations.
173
/// </summary>
174
/// <remarks>
175
/// This event has to be <c>static</c> because the client is unable to obtain a reference to the <c>HttpDownloader</c> instance (updater design flaw).
176
/// </remarks>
177
public static event DownloadTotalSizeCalculationProgressEventHandler DownloadTotalSizeCalculationProgress;
178![](/Images/OutliningIndicators/InBlock.gif)
179![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
180
/// Fires when the HTTP downloader has finished calculating file sizes.
181
/// </summary>
182
/// <remarks>
183
/// This event has to be <c>static</c> because the client is unable to obtain a reference to the <c>HttpDownloader</c> instance (updater design flaw).
184
/// </remarks>
185
public static event DownloadTotalSizeCalculationCompletedEventHandler DownloadTotalSizeCalculationCompleted;
186![](/Images/OutliningIndicators/InBlock.gif)
187![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
188
/// Fired when the HTTP downloader begins downloading files.
189
/// </summary>
190
public event DownloadTaskStartedEventHandler DownloadStarted;
191![](/Images/OutliningIndicators/InBlock.gif)
192![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
193
/// Fired whenever the HTTP downloader has progress information to report about the current downloads.
194
/// </summary>
195
public event DownloadTaskProgressEventHandler DownloadProgress;
196![](/Images/OutliningIndicators/InBlock.gif)
197![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
198
/// Fired when the HTTP downloader has finished downloading.
199
/// </summary>
200
public event DownloadTaskCompletedEventHandler DownloadCompleted;
201![](/Images/OutliningIndicators/InBlock.gif)
202![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
203
/// Fired when an error occurs in the HTTP downloader whilst attempting to download updates.
204
/// </summary>
205
public event DownloadTaskErrorEventHandler DownloadError;
206![](/Images/OutliningIndicators/InBlock.gif)
207![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
208
/// Used to invoke the <see cref="OnDownloadTotalSizeCalculationStarted"/> method.
209
/// </summary>
210
internal delegate void OnDownloadTotalSizeCalculationStartedEventHandler(TaskEventArgs e);
211![](/Images/OutliningIndicators/InBlock.gif)
212![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
213
/// Fires the <see cref="DownloadTotalSizeCalculationStarted"/> method.
214
/// </summary>
215
private void OnDownloadTotalSizeCalculationStarted(TaskEventArgs e)
216![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
217
if (DownloadTotalSizeCalculationStarted != null)
218![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
219
DownloadTotalSizeCalculationStarted(this, e);
220
}
221
}
222![](/Images/OutliningIndicators/InBlock.gif)
223![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
224
/// Used to invoke the <see cref="OnDownloadTotalSizeCalculationProgress"/> method.
225
/// </summary>
226
internal delegate void OnDownloadTotalSizeCalculationProgressEventHandler(DownloadTotalSizeCalculationProgressEventArgs e);
227![](/Images/OutliningIndicators/InBlock.gif)
228![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
229
/// Fires the <see cref="DownloadTotalSizeCalculationProgress"/> method.
230
/// </summary>
231
private void OnDownloadTotalSizeCalculationProgress(DownloadTotalSizeCalculationProgressEventArgs e)
232![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
233
if (DownloadTotalSizeCalculationProgress != null)
234![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
235
DownloadTotalSizeCalculationProgress(this, e);
236
}
237
}
238![](/Images/OutliningIndicators/InBlock.gif)
239![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
240
/// Used to invoke the <see cref="OnDownloadTotalSizeCalculationCompleted"/> method.
241
/// </summary>
242
internal delegate void OnDownloadTotalSizeCalculationCompletedEventHandler(TaskEventArgs e);
243![](/Images/OutliningIndicators/InBlock.gif)
244![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
245
/// Fires the <see cref="DownloadTotalSizeCalculationCompleted"/> method.
246
/// </summary>
247
private void OnDownloadTotalSizeCalculationCompleted(TaskEventArgs e)
248![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
249
if (DownloadTotalSizeCalculationCompleted != null)
250![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
251
DownloadTotalSizeCalculationCompleted(this, e);
252
}
253
}
254
255![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
256
/// Fires the <see cref="DownloadStarted"/> method.
257
/// </summary>
258
private void OnDownloadStarted(TaskEventArgs e)
259![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
260
if (DownloadStarted != null)
261![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
262
DownloadStarted(this, e);
263
}
264
}
265
266![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
267
/// Used to invoke the <see cref="OnDownloadProgress"/> method.
268
/// </summary>
269
internal delegate void OnDownloadProgressEventHandler(DownloadTaskProgressEventArgs e);
270![](/Images/OutliningIndicators/InBlock.gif)
271![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
272
/// Fires the <see cref="DownloadProgress"/> method.
273
/// </summary>
274
private void OnDownloadProgress(DownloadTaskProgressEventArgs e)
275![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
276
lock (LOCK)
277![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
278
if (DownloadProgress != null)
279![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
280
DownloadProgress(this, e);
281
}
282
}
283
}
284![](/Images/OutliningIndicators/InBlock.gif)
285![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
286
/// Used to invoke the <see cref="OnDownloadCompleted"/> method.
287
/// </summary>
288
internal delegate void OnDownloadCompletedEventHandler(TaskEventArgs e);
289
290![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
291
/// Fires the <see cref="DownloadCompleted"/> method.
292
/// </summary>
293
private void OnDownloadCompleted(TaskEventArgs e)
294![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
295
if (DownloadCompleted != null)
296![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
297
DownloadCompleted(this, e);
298
}
299
}
300![](/Images/OutliningIndicators/InBlock.gif)
301![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
302
/// Fires the <see cref="DownloadError"/> method.
303
/// </summary>
304
private void OnDownloadError(DownloadTaskErrorEventArgs e)
305![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
306
if (DownloadError != null)
307![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
308
DownloadError(this, e);
309
}
310
}
311![](/Images/OutliningIndicators/InBlock.gif)
312![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
313
/// Performs the actual downloading of updated files.
314
/// </summary>
315
private class AsyncDownloader
316![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
317![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
318
/// The task whose files will be downloaded.
319
/// </summary>
320
private UpdaterTask _task;
321![](/Images/OutliningIndicators/InBlock.gif)
322![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
323
/// Contains configuration settings.
324
/// </summary>
325
//private HttpDownloaderProviderData _configuration;
326![](/Images/OutliningIndicators/InBlock.gif)
327![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
328
/// Stores the last time a download progress report was issued.
329
/// </summary>
330
private DateTime _lastProgressReport;
331![](/Images/OutliningIndicators/InBlock.gif)
332![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
333
/// The delegate to invoke to report download progress.
334
/// </summary>
335
private OnDownloadProgressEventHandler _progressDelegate;
336![](/Images/OutliningIndicators/InBlock.gif)
337![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
338
/// The delegate to invoke to report that file size calculations have started.
339
/// </summary>
340
private OnDownloadTotalSizeCalculationStartedEventHandler _totalSizeStarted;
341![](/Images/OutliningIndicators/InBlock.gif)
342![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
343
/// The delegate to invoke to report file size calculations progress.
344
/// </summary>
345
private OnDownloadTotalSizeCalculationProgressEventHandler _totalSizeProgress;
346![](/Images/OutliningIndicators/InBlock.gif)
347![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
348
/// The delegate to invoke to report that file size calculations have completed.
349
/// </summary>
350
private OnDownloadTotalSizeCalculationCompletedEventHandler _totalSizeCompleted;
351![](/Images/OutliningIndicators/InBlock.gif)
352![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
353
/// The delegate to invoke to report that the download has completed.
354
/// </summary>
355
private OnDownloadCompletedEventHandler _downloadCompleted;
356![](/Images/OutliningIndicators/InBlock.gif)
357![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
358
/// The buffer used whilst downloading data.
359
/// </summary>
360
private byte[] _buffer;
361![](/Images/OutliningIndicators/InBlock.gif)
362![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
363
/// Set to <c>true</c> if the download completes successfully.
364
/// </summary>
365
private bool _isComplete;
366![](/Images/OutliningIndicators/InBlock.gif)
367![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
368
/// Any exception that occurred during the download.
369
/// </summary>
370
private Exception _exception;
371![](/Images/OutliningIndicators/InBlock.gif)
372![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
373
/// Synchronisation object.
374
/// </summary>
375
private readonly object LOCK;
376![](/Images/OutliningIndicators/InBlock.gif)
377![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
378
/// Gets or sets a value indicating whether the download completed successfully.
379
/// </summary>
380
internal bool IsComplete
381![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
382
get
383![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
384
lock (LOCK)
385![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
386
return _isComplete;
387
}
388
}
389
set
390![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
391
lock (LOCK)
392![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
393
_isComplete = value;
394
}
395
}
396
}
397![](/Images/OutliningIndicators/InBlock.gif)
398![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
399
/// Gets or sets an exception that occurred during the download process.
400
/// </summary>
401
internal Exception Exception
402![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
403
get
404![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
405
lock (LOCK)
406![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
407
return _exception;
408
}
409
}
410
set
411![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
412
lock (LOCK)
413![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
414
_exception = value;
415
}
416
}
417
}
418![](/Images/OutliningIndicators/InBlock.gif)
419![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
420
/// Constructs an <c>AsyncDownloader</c> instance.
421
/// </summary>
422
internal AsyncDownloader(UpdaterTask task, OnDownloadProgressEventHandler progressDelegate, OnDownloadTotalSizeCalculationStartedEventHandler totalSizeStarted, OnDownloadTotalSizeCalculationProgressEventHandler totalSizeProgress, OnDownloadTotalSizeCalculationCompletedEventHandler totalSizeCompleted, OnDownloadCompletedEventHandler downloadCompleted)
423![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
424
LOCK = new object();
425
_task = task;
426
//_configuration = configuration;
427
_progressDelegate = progressDelegate;
428
_totalSizeStarted = totalSizeStarted;
429
_totalSizeProgress = totalSizeProgress;
430
_totalSizeCompleted = totalSizeCompleted;
431
_downloadCompleted = downloadCompleted;
432
_buffer = new byte[1024];
433
_lastProgressReport = DateTime.MinValue;
434
}
435![](/Images/OutliningIndicators/InBlock.gif)
436![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
437
/// Performs the download operation.
438
/// </summary>
439
internal void Download()
440![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
441
long totalBytes = 0;
442
long transferredBytes = 0;
443
WebProxy webProxy = WebProxy.GetDefaultProxy();
444![](/Images/OutliningIndicators/InBlock.gif)
445
if (webProxy != null)
446![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
447
//not sure why this isn't default behaviour but it isn't. This ensures the downloader works when used from behind a proxy that requires authentication (assuming
448
//authentication information is set up in IE)
449
webProxy.Credentials = CredentialCache.DefaultCredentials;
450
}
451![](/Images/OutliningIndicators/InBlock.gif)
452
try
453![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
454
_totalSizeStarted(new TaskEventArgs(_task));
455![](/Images/OutliningIndicators/InBlock.gif)
456
//first determine the total content length
457
for (int i = 0; i < _task.Manifest.Files.Count; ++i)
458![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
459
FileManifest file = _task.Manifest.Files[i];
460
string uri = GetUri(file);
461
WebRequest webRequest = WebRequest.Create(uri);
462
webRequest.Proxy = webProxy;
463
webRequest.Method = "GET";
464
WebResponse webResponse = webRequest.GetResponse();
465
totalBytes += webResponse.ContentLength;
466
webResponse.Close();
467
_totalSizeProgress(new DownloadTotalSizeCalculationProgressEventArgs(_task.Manifest.Files.Count, i + 1));
468
}
469![](/Images/OutliningIndicators/InBlock.gif)
470
_totalSizeCompleted(new TaskEventArgs(_task));
471![](/Images/OutliningIndicators/InBlock.gif)
472
//now download each file
473
for (int i = 0; i < _task.Manifest.Files.Count; ++i)
474![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
475
FileManifest file = _task.Manifest.Files[i];
476
string uri = GetUri(file);
477
WebRequest webRequest = WebRequest.Create(uri);
478
webRequest.Proxy = webProxy;
479
WebResponse webResponse = webRequest.GetResponse();
480
string outFile = Path.Combine(_task.DownloadFilesBase, file.Source);
481
int read = 0;
482![](/Images/OutliningIndicators/InBlock.gif)
483
//make sure the destination directory exists
484
if (!Directory.Exists(Path.GetDirectoryName(outFile)))
485![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
486
Directory.CreateDirectory(Path.GetDirectoryName(outFile));
487
}
488![](/Images/OutliningIndicators/InBlock.gif)
489
using (Stream responseStream = webResponse.GetResponseStream())
490
using (Stream fileStream = new FileStream(outFile, FileMode.Create, FileAccess.Write))
491![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
492
while ((read = responseStream.Read(_buffer, 0, _buffer.Length)) != 0)
493![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
494
transferredBytes += read;
495
fileStream.Write(_buffer, 0, read);
496
TimeSpan timeSinceLastProgressReport = DateTime.Now - _lastProgressReport;
497![](/Images/OutliningIndicators/InBlock.gif)
498
//if ((_configuration.DownloadProgressMaximumFrequency == 0) || (timeSinceLastProgressReport.TotalMilliseconds > _configuration.DownloadProgressMaximumFrequency))
499
//{
500
// _lastProgressReport = DateTime.Now;
501
// _progressDelegate(new DownloadTaskProgressEventArgs(totalBytes, transferredBytes, _task.Manifest.Files.Count, i, _task));
502
//}
503
}
504![](/Images/OutliningIndicators/InBlock.gif)
505
//final progress report
506
_progressDelegate(new DownloadTaskProgressEventArgs(totalBytes, transferredBytes, _task.Manifest.Files.Count, i, _task));
507
}
508![](/Images/OutliningIndicators/InBlock.gif)
509
webResponse.Close();
510
}
511
}
512
catch (Exception e)
513![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
514
if (!(e is ThreadAbortException))
515![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
516
Exception = e;
517
}
518
}
519![](/Images/OutliningIndicators/InBlock.gif)
520
//fire the complete event if no error occurred
521
if (Exception == null)
522![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
523
_downloadCompleted(new TaskEventArgs(_task));
524
}
525![](/Images/OutliningIndicators/InBlock.gif)
526
//if the thread is aborted, this won't execute because the ThreadAbortException will continue propogating
527
IsComplete = true;
528
}
529![](/Images/OutliningIndicators/InBlock.gif)
530![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
531
/// Obtains a URI for the specified file.
532
/// </summary>
533
private string GetUri(FileManifest file)
534![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
535
return string.Format("{0}{1}", _task.Manifest.Files.Base, file.Source);
536
}
537
}
538
}
539
}
540
![](/Images/OutliningIndicators/ContractedBlock.gif)
HttpDownloaderProviderData
1
using System;
2
using System.Xml.Serialization;
3
using Microsoft.ApplicationBlocks.Updater.Configuration;
4
using Microsoft.ApplicationBlocks.Updater.Downloaders;
5
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ObjectBuilder;
6
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
7
using System.Configuration;
8
using Microsoft.ApplicationBlocks.Updater;
9
namespace x.HttpDownloader
10![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
11![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
12
/// Contains configuration for the <see cref="HttpDownloader"/>.
13
/// </summary>
14
//[XmlRoot("downloader", Namespace = ApplicationUpdaterSettings.ConfigurationNamespace)]
15
[Assembler(typeof(HttpDownloaderAssembler))]
16
public class HttpDownloaderProviderData : DownloaderProviderData
17![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
18![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
19
/// See <see cref="DownloadBufferSize"/>.
20
/// </summary>
21
private int _downloadBufferSize;
22![](/Images/OutliningIndicators/InBlock.gif)
23![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
24
/// See <see cref="DownloadProgressMaximumFrequency"/>
25
/// </summary>
26
private int _downloadProgressMaximumProgress;
27![](/Images/OutliningIndicators/InBlock.gif)
28![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
29
/// The minimum value that can be assigned to <see cref="DownloadBufferSize"/>.
30
/// </summary>
31
private const int DOWNLOAD_BUFFER_SIZE_MIN = 256;
32![](/Images/OutliningIndicators/InBlock.gif)
33![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
34
/// The maximum value that can be assigned to <see cref="DownloadBufferSize"/>.
35
/// </summary>
36
private const int DOWNLOAD_BUFFER_SIZE_MAX = 10240;
37![](/Images/OutliningIndicators/InBlock.gif)
38![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
39
/// The minimum value that can be assigned to <see cref="DownloadProgressMaximumFrequency"/>.
40
/// </summary>
41
private const int DOWNLOAD_PROGRESS_MAXIMUM_FREQUENCY_MIN = 0;
42
43![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
44
/// The maximum value that can be assigned to <see cref="DownloadProgressMaximumFrequency"/>.
45
/// </summary>
46
private const int DOWNLOAD_PROGRESS_MAXIMUM_FREQUENCY_MAX = 5000;
47![](/Images/OutliningIndicators/InBlock.gif)
48![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
49
/// Gets or sets the buffer size, in bytes, used whilst downloading files.
50
/// </summary>
51
/// <remarks>
52
/// The HTTP downloader reports progress each time it fills the download buffer. Therefore, larger buffer sizes will result
53
/// in fewer progress reports.
54
/// </remarks>
55
//[ConfigurationProperty(_downloadBufferSize, IsRequired = false)]
56
public int DownloadBufferSize
57![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
58
get
59![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
60
return _downloadBufferSize;
61
}
62
set
63![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
64
if ((value < DOWNLOAD_BUFFER_SIZE_MIN) || (value > DOWNLOAD_BUFFER_SIZE_MAX))
65![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
66
throw new ArgumentException(string.Format("DownloadBufferSize must be between {0} and {1}", DOWNLOAD_BUFFER_SIZE_MIN, DOWNLOAD_BUFFER_SIZE_MAX));
67
}
68![](/Images/OutliningIndicators/InBlock.gif)
69
_downloadBufferSize = value;
70
}
71
}
72![](/Images/OutliningIndicators/InBlock.gif)
73![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
74
/// Gets or sets the maximum frequency, in milliseconds, that progress will be reported by the HTTP downloader.
75
/// </summary>
76
/// <remarks>
77
/// <para>
78
/// This property allows you to limit the number of progress reports issued by the HTTP downloader. The downloader will ensure that
79
/// the amount of time specified by this property has elapsed prior to issuing another progress report. If enough time has not elapsed
80
/// then the downloader will not issue a progress report at that time.
81
/// </para>
82
/// <para>
83
/// Setting this property to <c>0</c> ensures that the downloader always reports progress, regardless of the amount of time that has
84
/// elapsed since the last progress report.
85
/// </para>
86
/// </remarks>
87
//[XmlElement("downloadProgressMaximumFrequency")]
88
public int DownloadProgressMaximumFrequency
89![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
90
get
91![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
92
return _downloadProgressMaximumProgress;
93
}
94
set
95![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
96
if ((value < DOWNLOAD_PROGRESS_MAXIMUM_FREQUENCY_MIN) || (value > DOWNLOAD_PROGRESS_MAXIMUM_FREQUENCY_MAX))
97![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
98
throw new ArgumentException(string.Format("DownloadProgressMaximumFrequency must be between {0} and {1}", DOWNLOAD_PROGRESS_MAXIMUM_FREQUENCY_MIN, DOWNLOAD_PROGRESS_MAXIMUM_FREQUENCY_MAX));
99
}
100![](/Images/OutliningIndicators/InBlock.gif)
101
_downloadProgressMaximumProgress = value;
102
}
103
}
104![](/Images/OutliningIndicators/InBlock.gif)
105![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
106
/// Default constructor.
107
/// </summary>
108
public HttpDownloaderProviderData()
109![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
110
DownloadBufferSize = 1024;
111
}
112
}
113![](/Images/OutliningIndicators/InBlock.gif)
114
public class HttpDownloaderAssembler : IAssembler<Microsoft.ApplicationBlocks.Updater.IDownloader, DownloaderProviderData>
115![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
116
public IDownloader Assemble(Microsoft.Practices.ObjectBuilder.IBuilderContext context, DownloaderProviderData objectConfiguration, IConfigurationSource configurationSource, ConfigurationReflectionCache reflectionCache)
117![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
118
HttpDownloaderProviderData bitsData = (HttpDownloaderProviderData)objectConfiguration;
119
return new HttpDownloader();
120
}
121
}
122
}
123
你需要Enterprise Libary 2006
![](/Images/OutliningIndicators/ContractedBlock.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
1
![](/Images/OutliningIndicators/None.gif)
2
![](/Images/OutliningIndicators/None.gif)
3
![](/Images/OutliningIndicators/None.gif)
4
![](/Images/OutliningIndicators/None.gif)
5
![](/Images/OutliningIndicators/None.gif)
6
![](/Images/OutliningIndicators/None.gif)
7
![](/Images/OutliningIndicators/None.gif)
8
![](/Images/OutliningIndicators/None.gif)
9
![](/Images/OutliningIndicators/None.gif)
10
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
![](/Images/dot.gif)
11
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
12
![](/Images/OutliningIndicators/InBlock.gif)
13
![](/Images/OutliningIndicators/InBlock.gif)
14
![](/Images/OutliningIndicators/InBlock.gif)
15
![](/Images/OutliningIndicators/InBlock.gif)
16
![](/Images/OutliningIndicators/InBlock.gif)
17
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
18
![](/Images/OutliningIndicators/InBlock.gif)
19
![](/Images/OutliningIndicators/InBlock.gif)
20
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
21
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
22
![](/Images/OutliningIndicators/InBlock.gif)
23
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
24
![](/Images/OutliningIndicators/InBlock.gif)
25
![](/Images/OutliningIndicators/InBlock.gif)
26
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
27
![](/Images/OutliningIndicators/InBlock.gif)
28
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
29
![](/Images/OutliningIndicators/InBlock.gif)
30
![](/Images/OutliningIndicators/InBlock.gif)
31
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
32
![](/Images/OutliningIndicators/InBlock.gif)
33
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
34
![](/Images/OutliningIndicators/InBlock.gif)
35
![](/Images/OutliningIndicators/InBlock.gif)
36
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
37
![](/Images/OutliningIndicators/InBlock.gif)
38
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
39
![](/Images/OutliningIndicators/InBlock.gif)
40
![](/Images/OutliningIndicators/InBlock.gif)
41
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
42
![](/Images/OutliningIndicators/InBlock.gif)
43
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
44
![](/Images/OutliningIndicators/InBlock.gif)
45
![](/Images/OutliningIndicators/InBlock.gif)
46
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
47
![](/Images/OutliningIndicators/InBlock.gif)
48
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
49
![](/Images/OutliningIndicators/InBlock.gif)
50
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
51
![](/Images/OutliningIndicators/InBlock.gif)
52
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
53
![](/Images/OutliningIndicators/InBlock.gif)
54
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
55
![](/Images/OutliningIndicators/InBlock.gif)
56
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
57
![](/Images/OutliningIndicators/InBlock.gif)
58
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
59
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
60
![](/Images/OutliningIndicators/InBlock.gif)
61
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
62
![](/Images/OutliningIndicators/InBlock.gif)
63
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
64
![](/Images/OutliningIndicators/InBlock.gif)
65
![](/Images/OutliningIndicators/InBlock.gif)
66
![](/Images/OutliningIndicators/InBlock.gif)
67
![](/Images/OutliningIndicators/InBlock.gif)
68
![](/Images/OutliningIndicators/InBlock.gif)
69
![](/Images/OutliningIndicators/InBlock.gif)
70
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
71
![](/Images/OutliningIndicators/InBlock.gif)
72
![](/Images/OutliningIndicators/InBlock.gif)
73
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
74
![](/Images/OutliningIndicators/InBlock.gif)
75
![](/Images/OutliningIndicators/InBlock.gif)
76
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
77
![](/Images/OutliningIndicators/InBlock.gif)
78
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
79
![](/Images/OutliningIndicators/InBlock.gif)
80
![](/Images/OutliningIndicators/InBlock.gif)
81
![](/Images/OutliningIndicators/InBlock.gif)
82
![](/Images/OutliningIndicators/InBlock.gif)
83
![](/Images/OutliningIndicators/InBlock.gif)
84
![](/Images/OutliningIndicators/InBlock.gif)
85
![](/Images/OutliningIndicators/InBlock.gif)
86
![](/Images/OutliningIndicators/InBlock.gif)
87
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
88
![](/Images/OutliningIndicators/InBlock.gif)
89
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
90
![](/Images/OutliningIndicators/InBlock.gif)
91
![](/Images/OutliningIndicators/InBlock.gif)
92
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
93
![](/Images/OutliningIndicators/InBlock.gif)
94
![](/Images/OutliningIndicators/InBlock.gif)
95
![](/Images/OutliningIndicators/InBlock.gif)
96
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
97
![](/Images/OutliningIndicators/InBlock.gif)
98
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
99
![](/Images/OutliningIndicators/InBlock.gif)
100
![](/Images/OutliningIndicators/InBlock.gif)
101
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
102
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
103
![](/Images/OutliningIndicators/InBlock.gif)
104
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
105
![](/Images/OutliningIndicators/InBlock.gif)
106
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
107
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
108
![](/Images/OutliningIndicators/InBlock.gif)
109
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
110
![](/Images/OutliningIndicators/InBlock.gif)
111
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
112
![](/Images/OutliningIndicators/InBlock.gif)
113
![](/Images/OutliningIndicators/InBlock.gif)
114
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
115
![](/Images/OutliningIndicators/InBlock.gif)
116
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
117
![](/Images/OutliningIndicators/InBlock.gif)
118
![](/Images/OutliningIndicators/InBlock.gif)
119
![](/Images/OutliningIndicators/InBlock.gif)
120
![](/Images/OutliningIndicators/InBlock.gif)
121
![](/Images/OutliningIndicators/InBlock.gif)
122
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
123
![](/Images/OutliningIndicators/InBlock.gif)
124
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
125
![](/Images/OutliningIndicators/InBlock.gif)
126
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
127
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
128
![](/Images/OutliningIndicators/InBlock.gif)
129
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
130
![](/Images/OutliningIndicators/InBlock.gif)
131
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
132
![](/Images/OutliningIndicators/InBlock.gif)
133
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
134
![](/Images/OutliningIndicators/InBlock.gif)
135
![](/Images/OutliningIndicators/InBlock.gif)
136
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
137
![](/Images/OutliningIndicators/InBlock.gif)
138
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
139
![](/Images/OutliningIndicators/InBlock.gif)
140
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
141
![](/Images/OutliningIndicators/InBlock.gif)
142
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
143
![](/Images/OutliningIndicators/InBlock.gif)
144
![](/Images/OutliningIndicators/InBlock.gif)
145
![](/Images/OutliningIndicators/InBlock.gif)
146
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
147
![](/Images/OutliningIndicators/InBlock.gif)
148
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
149
![](/Images/OutliningIndicators/InBlock.gif)
150
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
151
![](/Images/OutliningIndicators/InBlock.gif)
152
![](/Images/OutliningIndicators/InBlock.gif)
153
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
154
![](/Images/OutliningIndicators/InBlock.gif)
155
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
156
![](/Images/OutliningIndicators/InBlock.gif)
157
![](/Images/OutliningIndicators/InBlock.gif)
158
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
159
![](/Images/OutliningIndicators/InBlock.gif)
160
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
161
![](/Images/OutliningIndicators/InBlock.gif)
162
![](/Images/OutliningIndicators/InBlock.gif)
163
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
164
![](/Images/OutliningIndicators/InBlock.gif)
165
![](/Images/OutliningIndicators/InBlock.gif)
166
![](/Images/OutliningIndicators/InBlock.gif)
167
![](/Images/OutliningIndicators/InBlock.gif)
168
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
169
![](/Images/OutliningIndicators/InBlock.gif)
170
![](/Images/OutliningIndicators/InBlock.gif)
171
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
172
![](/Images/OutliningIndicators/InBlock.gif)
173
![](/Images/OutliningIndicators/InBlock.gif)
174
![](/Images/OutliningIndicators/InBlock.gif)
175
![](/Images/OutliningIndicators/InBlock.gif)
176
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
177
![](/Images/OutliningIndicators/InBlock.gif)
178
![](/Images/OutliningIndicators/InBlock.gif)
179
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
180
![](/Images/OutliningIndicators/InBlock.gif)
181
![](/Images/OutliningIndicators/InBlock.gif)
182
![](/Images/OutliningIndicators/InBlock.gif)
183
![](/Images/OutliningIndicators/InBlock.gif)
184
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
185
![](/Images/OutliningIndicators/InBlock.gif)
186
![](/Images/OutliningIndicators/InBlock.gif)
187
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
188
![](/Images/OutliningIndicators/InBlock.gif)
189
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
190
![](/Images/OutliningIndicators/InBlock.gif)
191
![](/Images/OutliningIndicators/InBlock.gif)
192
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
193
![](/Images/OutliningIndicators/InBlock.gif)
194
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
195
![](/Images/OutliningIndicators/InBlock.gif)
196
![](/Images/OutliningIndicators/InBlock.gif)
197
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
198
![](/Images/OutliningIndicators/InBlock.gif)
199
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
200
![](/Images/OutliningIndicators/InBlock.gif)
201
![](/Images/OutliningIndicators/InBlock.gif)
202
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
203
![](/Images/OutliningIndicators/InBlock.gif)
204
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
205
![](/Images/OutliningIndicators/InBlock.gif)
206
![](/Images/OutliningIndicators/InBlock.gif)
207
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
208
![](/Images/OutliningIndicators/InBlock.gif)
209
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
210
![](/Images/OutliningIndicators/InBlock.gif)
211
![](/Images/OutliningIndicators/InBlock.gif)
212
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
213
![](/Images/OutliningIndicators/InBlock.gif)
214
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
215
![](/Images/OutliningIndicators/InBlock.gif)
216
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
217
![](/Images/OutliningIndicators/InBlock.gif)
218
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
219
![](/Images/OutliningIndicators/InBlock.gif)
220
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
221
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
222
![](/Images/OutliningIndicators/InBlock.gif)
223
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
224
![](/Images/OutliningIndicators/InBlock.gif)
225
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
226
![](/Images/OutliningIndicators/InBlock.gif)
227
![](/Images/OutliningIndicators/InBlock.gif)
228
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
229
![](/Images/OutliningIndicators/InBlock.gif)
230
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
231
![](/Images/OutliningIndicators/InBlock.gif)
232
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
233
![](/Images/OutliningIndicators/InBlock.gif)
234
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
235
![](/Images/OutliningIndicators/InBlock.gif)
236
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
237
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
238
![](/Images/OutliningIndicators/InBlock.gif)
239
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
240
![](/Images/OutliningIndicators/InBlock.gif)
241
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
242
![](/Images/OutliningIndicators/InBlock.gif)
243
![](/Images/OutliningIndicators/InBlock.gif)
244
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
245
![](/Images/OutliningIndicators/InBlock.gif)
246
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
247
![](/Images/OutliningIndicators/InBlock.gif)
248
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
249
![](/Images/OutliningIndicators/InBlock.gif)
250
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
251
![](/Images/OutliningIndicators/InBlock.gif)
252
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
253
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
254
![](/Images/OutliningIndicators/InBlock.gif)
255
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
256
![](/Images/OutliningIndicators/InBlock.gif)
257
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
258
![](/Images/OutliningIndicators/InBlock.gif)
259
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
260
![](/Images/OutliningIndicators/InBlock.gif)
261
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
262
![](/Images/OutliningIndicators/InBlock.gif)
263
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
264
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
265
![](/Images/OutliningIndicators/InBlock.gif)
266
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
267
![](/Images/OutliningIndicators/InBlock.gif)
268
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
269
![](/Images/OutliningIndicators/InBlock.gif)
270
![](/Images/OutliningIndicators/InBlock.gif)
271
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
272
![](/Images/OutliningIndicators/InBlock.gif)
273
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
274
![](/Images/OutliningIndicators/InBlock.gif)
275
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
276
![](/Images/OutliningIndicators/InBlock.gif)
277
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
278
![](/Images/OutliningIndicators/InBlock.gif)
279
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
280
![](/Images/OutliningIndicators/InBlock.gif)
281
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
282
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
283
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
284
![](/Images/OutliningIndicators/InBlock.gif)
285
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
286
![](/Images/OutliningIndicators/InBlock.gif)
287
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
288
![](/Images/OutliningIndicators/InBlock.gif)
289
![](/Images/OutliningIndicators/InBlock.gif)
290
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
291
![](/Images/OutliningIndicators/InBlock.gif)
292
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
293
![](/Images/OutliningIndicators/InBlock.gif)
294
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
295
![](/Images/OutliningIndicators/InBlock.gif)
296
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
297
![](/Images/OutliningIndicators/InBlock.gif)
298
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
299
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
300
![](/Images/OutliningIndicators/InBlock.gif)
301
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
302
![](/Images/OutliningIndicators/InBlock.gif)
303
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
304
![](/Images/OutliningIndicators/InBlock.gif)
305
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
306
![](/Images/OutliningIndicators/InBlock.gif)
307
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
308
![](/Images/OutliningIndicators/InBlock.gif)
309
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
310
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
311
![](/Images/OutliningIndicators/InBlock.gif)
312
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
313
![](/Images/OutliningIndicators/InBlock.gif)
314
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
315
![](/Images/OutliningIndicators/InBlock.gif)
316
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
317
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
318
![](/Images/OutliningIndicators/InBlock.gif)
319
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
320
![](/Images/OutliningIndicators/InBlock.gif)
321
![](/Images/OutliningIndicators/InBlock.gif)
322
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
323
![](/Images/OutliningIndicators/InBlock.gif)
324
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
325
![](/Images/OutliningIndicators/InBlock.gif)
326
![](/Images/OutliningIndicators/InBlock.gif)
327
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
328
![](/Images/OutliningIndicators/InBlock.gif)
329
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
330
![](/Images/OutliningIndicators/InBlock.gif)
331
![](/Images/OutliningIndicators/InBlock.gif)
332
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
333
![](/Images/OutliningIndicators/InBlock.gif)
334
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
335
![](/Images/OutliningIndicators/InBlock.gif)
336
![](/Images/OutliningIndicators/InBlock.gif)
337
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
338
![](/Images/OutliningIndicators/InBlock.gif)
339
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
340
![](/Images/OutliningIndicators/InBlock.gif)
341
![](/Images/OutliningIndicators/InBlock.gif)
342
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
343
![](/Images/OutliningIndicators/InBlock.gif)
344
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
345
![](/Images/OutliningIndicators/InBlock.gif)
346
![](/Images/OutliningIndicators/InBlock.gif)
347
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
348
![](/Images/OutliningIndicators/InBlock.gif)
349
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
350
![](/Images/OutliningIndicators/InBlock.gif)
351
![](/Images/OutliningIndicators/InBlock.gif)
352
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
353
![](/Images/OutliningIndicators/InBlock.gif)
354
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
355
![](/Images/OutliningIndicators/InBlock.gif)
356
![](/Images/OutliningIndicators/InBlock.gif)
357
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
358
![](/Images/OutliningIndicators/InBlock.gif)
359
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
360
![](/Images/OutliningIndicators/InBlock.gif)
361
![](/Images/OutliningIndicators/InBlock.gif)
362
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
363
![](/Images/OutliningIndicators/InBlock.gif)
364
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
365
![](/Images/OutliningIndicators/InBlock.gif)
366
![](/Images/OutliningIndicators/InBlock.gif)
367
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
368
![](/Images/OutliningIndicators/InBlock.gif)
369
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
370
![](/Images/OutliningIndicators/InBlock.gif)
371
![](/Images/OutliningIndicators/InBlock.gif)
372
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
373
![](/Images/OutliningIndicators/InBlock.gif)
374
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
375
![](/Images/OutliningIndicators/InBlock.gif)
376
![](/Images/OutliningIndicators/InBlock.gif)
377
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
378
![](/Images/OutliningIndicators/InBlock.gif)
379
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
380
![](/Images/OutliningIndicators/InBlock.gif)
381
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
382
![](/Images/OutliningIndicators/InBlock.gif)
383
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
384
![](/Images/OutliningIndicators/InBlock.gif)
385
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
386
![](/Images/OutliningIndicators/InBlock.gif)
387
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
388
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
389
![](/Images/OutliningIndicators/InBlock.gif)
390
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
391
![](/Images/OutliningIndicators/InBlock.gif)
392
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
393
![](/Images/OutliningIndicators/InBlock.gif)
394
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
395
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
396
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
397
![](/Images/OutliningIndicators/InBlock.gif)
398
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
399
![](/Images/OutliningIndicators/InBlock.gif)
400
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
401
![](/Images/OutliningIndicators/InBlock.gif)
402
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
403
![](/Images/OutliningIndicators/InBlock.gif)
404
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
405
![](/Images/OutliningIndicators/InBlock.gif)
406
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
407
![](/Images/OutliningIndicators/InBlock.gif)
408
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
409
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
410
![](/Images/OutliningIndicators/InBlock.gif)
411
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
412
![](/Images/OutliningIndicators/InBlock.gif)
413
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
414
![](/Images/OutliningIndicators/InBlock.gif)
415
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
416
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
417
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
418
![](/Images/OutliningIndicators/InBlock.gif)
419
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
420
![](/Images/OutliningIndicators/InBlock.gif)
421
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
422
![](/Images/OutliningIndicators/InBlock.gif)
423
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
424
![](/Images/OutliningIndicators/InBlock.gif)
425
![](/Images/OutliningIndicators/InBlock.gif)
426
![](/Images/OutliningIndicators/InBlock.gif)
427
![](/Images/OutliningIndicators/InBlock.gif)
428
![](/Images/OutliningIndicators/InBlock.gif)
429
![](/Images/OutliningIndicators/InBlock.gif)
430
![](/Images/OutliningIndicators/InBlock.gif)
431
![](/Images/OutliningIndicators/InBlock.gif)
432
![](/Images/OutliningIndicators/InBlock.gif)
433
![](/Images/OutliningIndicators/InBlock.gif)
434
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
435
![](/Images/OutliningIndicators/InBlock.gif)
436
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
437
![](/Images/OutliningIndicators/InBlock.gif)
438
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
439
![](/Images/OutliningIndicators/InBlock.gif)
440
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
441
![](/Images/OutliningIndicators/InBlock.gif)
442
![](/Images/OutliningIndicators/InBlock.gif)
443
![](/Images/OutliningIndicators/InBlock.gif)
444
![](/Images/OutliningIndicators/InBlock.gif)
445
![](/Images/OutliningIndicators/InBlock.gif)
446
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
447
![](/Images/OutliningIndicators/InBlock.gif)
448
![](/Images/OutliningIndicators/InBlock.gif)
449
![](/Images/OutliningIndicators/InBlock.gif)
450
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
451
![](/Images/OutliningIndicators/InBlock.gif)
452
![](/Images/OutliningIndicators/InBlock.gif)
453
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
454
![](/Images/OutliningIndicators/InBlock.gif)
455
![](/Images/OutliningIndicators/InBlock.gif)
456
![](/Images/OutliningIndicators/InBlock.gif)
457
![](/Images/OutliningIndicators/InBlock.gif)
458
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
459
![](/Images/OutliningIndicators/InBlock.gif)
460
![](/Images/OutliningIndicators/InBlock.gif)
461
![](/Images/OutliningIndicators/InBlock.gif)
462
![](/Images/OutliningIndicators/InBlock.gif)
463
![](/Images/OutliningIndicators/InBlock.gif)
464
![](/Images/OutliningIndicators/InBlock.gif)
465
![](/Images/OutliningIndicators/InBlock.gif)
466
![](/Images/OutliningIndicators/InBlock.gif)
467
![](/Images/OutliningIndicators/InBlock.gif)
468
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
469
![](/Images/OutliningIndicators/InBlock.gif)
470
![](/Images/OutliningIndicators/InBlock.gif)
471
![](/Images/OutliningIndicators/InBlock.gif)
472
![](/Images/OutliningIndicators/InBlock.gif)
473
![](/Images/OutliningIndicators/InBlock.gif)
474
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
475
![](/Images/OutliningIndicators/InBlock.gif)
476
![](/Images/OutliningIndicators/InBlock.gif)
477
![](/Images/OutliningIndicators/InBlock.gif)
478
![](/Images/OutliningIndicators/InBlock.gif)
479
![](/Images/OutliningIndicators/InBlock.gif)
480
![](/Images/OutliningIndicators/InBlock.gif)
481
![](/Images/OutliningIndicators/InBlock.gif)
482
![](/Images/OutliningIndicators/InBlock.gif)
483
![](/Images/OutliningIndicators/InBlock.gif)
484
![](/Images/OutliningIndicators/InBlock.gif)
485
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
486
![](/Images/OutliningIndicators/InBlock.gif)
487
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
488
![](/Images/OutliningIndicators/InBlock.gif)
489
![](/Images/OutliningIndicators/InBlock.gif)
490
![](/Images/OutliningIndicators/InBlock.gif)
491
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
492
![](/Images/OutliningIndicators/InBlock.gif)
493
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
494
![](/Images/OutliningIndicators/InBlock.gif)
495
![](/Images/OutliningIndicators/InBlock.gif)
496
![](/Images/OutliningIndicators/InBlock.gif)
497
![](/Images/OutliningIndicators/InBlock.gif)
498
![](/Images/OutliningIndicators/InBlock.gif)
499
![](/Images/OutliningIndicators/InBlock.gif)
500
![](/Images/OutliningIndicators/InBlock.gif)
501
![](/Images/OutliningIndicators/InBlock.gif)
502
![](/Images/OutliningIndicators/InBlock.gif)
503
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
504
![](/Images/OutliningIndicators/InBlock.gif)
505
![](/Images/OutliningIndicators/InBlock.gif)
506
![](/Images/OutliningIndicators/InBlock.gif)
507
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
508
![](/Images/OutliningIndicators/InBlock.gif)
509
![](/Images/OutliningIndicators/InBlock.gif)
510
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
511
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
512
![](/Images/OutliningIndicators/InBlock.gif)
513
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
514
![](/Images/OutliningIndicators/InBlock.gif)
515
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
516
![](/Images/OutliningIndicators/InBlock.gif)
517
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
518
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
519
![](/Images/OutliningIndicators/InBlock.gif)
520
![](/Images/OutliningIndicators/InBlock.gif)
521
![](/Images/OutliningIndicators/InBlock.gif)
522
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
523
![](/Images/OutliningIndicators/InBlock.gif)
524
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
525
![](/Images/OutliningIndicators/InBlock.gif)
526
![](/Images/OutliningIndicators/InBlock.gif)
527
![](/Images/OutliningIndicators/InBlock.gif)
528
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
529
![](/Images/OutliningIndicators/InBlock.gif)
530
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
531
![](/Images/OutliningIndicators/InBlock.gif)
532
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
533
![](/Images/OutliningIndicators/InBlock.gif)
534
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
535
![](/Images/OutliningIndicators/InBlock.gif)
536
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
537
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
538
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
539
![](/Images/OutliningIndicators/ExpandedBlockEnd.gif)
540
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
1
![](/Images/OutliningIndicators/None.gif)
2
![](/Images/OutliningIndicators/None.gif)
3
![](/Images/OutliningIndicators/None.gif)
4
![](/Images/OutliningIndicators/None.gif)
5
![](/Images/OutliningIndicators/None.gif)
6
![](/Images/OutliningIndicators/None.gif)
7
![](/Images/OutliningIndicators/None.gif)
8
![](/Images/OutliningIndicators/None.gif)
9
![](/Images/OutliningIndicators/None.gif)
10
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
![](/Images/dot.gif)
11
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
12
![](/Images/OutliningIndicators/InBlock.gif)
13
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
14
![](/Images/OutliningIndicators/InBlock.gif)
15
![](/Images/OutliningIndicators/InBlock.gif)
16
![](/Images/OutliningIndicators/InBlock.gif)
17
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
18
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
19
![](/Images/OutliningIndicators/InBlock.gif)
20
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
21
![](/Images/OutliningIndicators/InBlock.gif)
22
![](/Images/OutliningIndicators/InBlock.gif)
23
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
24
![](/Images/OutliningIndicators/InBlock.gif)
25
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
26
![](/Images/OutliningIndicators/InBlock.gif)
27
![](/Images/OutliningIndicators/InBlock.gif)
28
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
29
![](/Images/OutliningIndicators/InBlock.gif)
30
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
31
![](/Images/OutliningIndicators/InBlock.gif)
32
![](/Images/OutliningIndicators/InBlock.gif)
33
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
34
![](/Images/OutliningIndicators/InBlock.gif)
35
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
36
![](/Images/OutliningIndicators/InBlock.gif)
37
![](/Images/OutliningIndicators/InBlock.gif)
38
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
39
![](/Images/OutliningIndicators/InBlock.gif)
40
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
41
![](/Images/OutliningIndicators/InBlock.gif)
42
![](/Images/OutliningIndicators/InBlock.gif)
43
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
44
![](/Images/OutliningIndicators/InBlock.gif)
45
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
46
![](/Images/OutliningIndicators/InBlock.gif)
47
![](/Images/OutliningIndicators/InBlock.gif)
48
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
49
![](/Images/OutliningIndicators/InBlock.gif)
50
![](/Images/OutliningIndicators/InBlock.gif)
51
![](/Images/OutliningIndicators/InBlock.gif)
52
![](/Images/OutliningIndicators/InBlock.gif)
53
![](/Images/OutliningIndicators/InBlock.gif)
54
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
55
![](/Images/OutliningIndicators/InBlock.gif)
56
![](/Images/OutliningIndicators/InBlock.gif)
57
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
58
![](/Images/OutliningIndicators/InBlock.gif)
59
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
60
![](/Images/OutliningIndicators/InBlock.gif)
61
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
62
![](/Images/OutliningIndicators/InBlock.gif)
63
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
64
![](/Images/OutliningIndicators/InBlock.gif)
65
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
66
![](/Images/OutliningIndicators/InBlock.gif)
67
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
68
![](/Images/OutliningIndicators/InBlock.gif)
69
![](/Images/OutliningIndicators/InBlock.gif)
70
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
71
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
72
![](/Images/OutliningIndicators/InBlock.gif)
73
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
74
![](/Images/OutliningIndicators/InBlock.gif)
75
![](/Images/OutliningIndicators/InBlock.gif)
76
![](/Images/OutliningIndicators/InBlock.gif)
77
![](/Images/OutliningIndicators/InBlock.gif)
78
![](/Images/OutliningIndicators/InBlock.gif)
79
![](/Images/OutliningIndicators/InBlock.gif)
80
![](/Images/OutliningIndicators/InBlock.gif)
81
![](/Images/OutliningIndicators/InBlock.gif)
82
![](/Images/OutliningIndicators/InBlock.gif)
83
![](/Images/OutliningIndicators/InBlock.gif)
84
![](/Images/OutliningIndicators/InBlock.gif)
85
![](/Images/OutliningIndicators/InBlock.gif)
86
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
87
![](/Images/OutliningIndicators/InBlock.gif)
88
![](/Images/OutliningIndicators/InBlock.gif)
89
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
90
![](/Images/OutliningIndicators/InBlock.gif)
91
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
92
![](/Images/OutliningIndicators/InBlock.gif)
93
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
94
![](/Images/OutliningIndicators/InBlock.gif)
95
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
96
![](/Images/OutliningIndicators/InBlock.gif)
97
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
98
![](/Images/OutliningIndicators/InBlock.gif)
99
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
100
![](/Images/OutliningIndicators/InBlock.gif)
101
![](/Images/OutliningIndicators/InBlock.gif)
102
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
103
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
104
![](/Images/OutliningIndicators/InBlock.gif)
105
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
106
![](/Images/OutliningIndicators/InBlock.gif)
107
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
108
![](/Images/OutliningIndicators/InBlock.gif)
109
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
110
![](/Images/OutliningIndicators/InBlock.gif)
111
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
112
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
113
![](/Images/OutliningIndicators/InBlock.gif)
114
![](/Images/OutliningIndicators/InBlock.gif)
115
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
116
![](/Images/OutliningIndicators/InBlock.gif)
117
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
118
![](/Images/OutliningIndicators/InBlock.gif)
119
![](/Images/OutliningIndicators/InBlock.gif)
120
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
121
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
122
![](/Images/OutliningIndicators/ExpandedBlockEnd.gif)
123
![](/Images/OutliningIndicators/None.gif)