-
Notifications
You must be signed in to change notification settings - Fork 16
/
DownloadScheduler.cs
117 lines (104 loc) · 3.28 KB
/
DownloadScheduler.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
using System;
using System.Threading;
namespace Downloader
{
public class DownloadScheduler : IDownloadScheduler
{
//constants
private const long SCHEDULER_LIMIT = 10;
//scheduler data
private long nextChunk;
private Thread[] schedulerThreads;
//chunk download jobs and exception
public Exception Error { private set; get; }
public Chunks Chunks { private set; get; }
/// <summary>
/// initialize the download scheduler
/// </summary>
/// <param name="chunks">the chunk download jobs</param>
public DownloadScheduler(Chunks chunks) { Chunks = chunks; }
/// <summary>
/// start the scheduler
/// </summary>
public void Start()
{
//little clean-up
Error = null;
nextChunk = 0;
//create new scheduler threads
schedulerThreads = new Thread[Math.Min(SCHEDULER_LIMIT, Chunks.ChunkCount)];
for (int i = 0; i < schedulerThreads.Length; i++)
schedulerThreads[i] = new Thread(() => Schedule());
//start all the scheduler threads
for (int i = 0; i < schedulerThreads.Length; i++) schedulerThreads[i].Start();
//wait for the scheduler threads to finish
for (int i = 0; i < schedulerThreads.Length; i++)
{
if (schedulerThreads[i].IsAlive)
{
schedulerThreads[i].Join();
}
if (Error != null)
{
throw Error;
}
}
}
/// <summary>
/// aborts the scheduler threads and waits for them
/// </summary>
public void Abort()
{
//abort all the threads
for (int i = 0; i < schedulerThreads.Length; i++)
{
if (schedulerThreads[i].IsAlive)
{
schedulerThreads[i].Abort();
}
}
//wait for all the threads to abort
for (int i = 0; i < schedulerThreads.Length; i++)
{
if (schedulerThreads[i].IsAlive)
{
schedulerThreads[i].Join();
}
}
}
/// <summary>
/// scheduler thread logic
/// </summary>
private void Schedule()
{
try
{
while (true)
{
long currentChunk = -1;
lock (Chunks)
{
//if next chunk available go to it
if (nextChunk < Chunks.ChunkCount)
{
currentChunk = nextChunk++;
}
}
//if ok download the next chunk
if (currentChunk != -1 && Error == null)
{
Chunks.DownloadChunk(currentChunk);
}
else
{
break;
}
}
}
catch (Exception e)
{
Error = e;
}
}
}
}