/*
* 2006.6.30
*
*
*
*/
using System;
using System.Collections.Generic;
using System.Text;
using System.Timers;
using System.ComponentModel;
using System.Threading;
using System.Collections;
using IReaper.FileData;
using IReaper.CourseData;
using IReaper.Properties;
using System.Net;
using System.Runtime.CompilerServices;
namespace IReaper.Running{
public class DownloadEngine
{
public static event EventHandler DownloadInvoked;
public static event EventHandler BeforeDownloadInvoked;
public static event EventHandler AfterDownloadInvoked;
static Queue<CourseFileData> queue;
static volatile List<WorkerThread> workers;
static volatile List<EventWaitHandle> workerWaitHandles;
static volatile List<EventWaitHandle> closeWaitHandles;
static volatile int maxThreadNumber;
static volatile int currentThreadNumber;
static AsyncOperation async;
static SendOrPostCallback doNothingCallback;
static AutoResetEvent addNewThreadWorkerHandler;
static ManualResetEvent pauseCheckHandler;
static ManualResetEvent queueCheckHandler;
static ManualResetEvent stopCheckHandler;
static EventWaitHandle[] entryWaitHandler;
static EventWaitHandle[] workerHandles;
//static bool isInited = false;
[MethodImpl(MethodImplOptions.Synchronized)]
public static void Init()
{
//if (isInited)
//{ return; }
//isInited = true;
doNothingCallback = new SendOrPostCallback(delegate(object obj) { ;});
CourseFileData.async.Post(new SendOrPostCallback(delegate(object obj)
{
async = AsyncOperationManager.CreateOperation("DownloadEngine");
}), null);
//
queue = new Queue<CourseFileData>();
//
workers = new List<WorkerThread>();
List<WorkerThread> list = new List<WorkerThread>();
//WaitHandle
workerWaitHandles = new List<EventWaitHandle>();
closeWaitHandles = new List<EventWaitHandle>();
//
maxThreadNumber = Settings.Default.MaxThread;
currentThreadNumber = 0;
//register setting changed
IReaper.Properties.Settings.Default.SettingChanging += new System.Configuration.SettingChangingEventHandler(Default_SettingChanging);
//addnewThreadWorkerHandler
addNewThreadWorkerHandler = new AutoResetEvent(false);
//
pauseCheckHandler = new ManualResetEvent(true);
//
queueCheckHandler = new ManualResetEvent(false);
//
stopCheckHandler = new ManualResetEvent(true);
//WaitHandler
entryWaitHandler = new EventWaitHandle[2];
entryWaitHandler[0] = queueCheckHandler;
entryWaitHandler[1] = stopCheckHandler;
//
AddMoreThread();
//
IReaper.Net.NetworkManager.SetConnectionLimit();
//listen to setting change
IReaper.Properties.Settings.Default.SettingsLoaded += new System.Configuration.SettingsLoadedEventHandler(SettingLoaded);
//
Thread thread = new Thread(new ThreadStart(Update));
thread.IsBackground = true;
thread.Start();
}
static void Default_SettingChanging(object sender, System.Configuration.SettingChangingEventArgs e)
{
if (e.SettingName == "MaxThread")
{
//
if (e.NewValue == null)
{ return; }
int newCount = (int)e.NewValue;
AlternateCurrentThread(newCount);
}
}
static void SettingLoaded(object sender, System.Configuration.SettingsLoadedEventArgs e)
{
int number = Settings.Default.MaxThread;
if (number != maxThreadNumber)
AlternateCurrentThread(number);
}
#region
public static void BeginAddCourseFileData()
{
try
{
if (BeforeDownloadInvoked != null)
BeforeDownloadInvoked(null, EventArgs.Empty);
}
catch { }
}
/// <summary>
///
/// </summary>
/// <param name="Data"></param>
public static void AddCourseFileData(CourseFileData Data)
{
if (Data == null)
return;
//
if (Data.RunState == RunningStatue.Running ||
Data.RunState == RunningStatue.RunQueued ||
Data.RunState == RunningStatue.RunRequest ||
Data.RunState == RunningStatue.StopRequest ||
Data.RunningWorker != null)
return;
//
if (Data.LifetimeStatue == LifetimePosition.DownloadProcessed)
return;
//
Data.RunState = RunningStatue.RunRequest;
//
if (Data.Storage.Index < 0)
{
CourseFileDataManager.ApplyNewStorage(ref Data.Storage);
}
lock (queue)
{
queue.Enqueue(Data);
try
{
if (DownloadInvoked != null)
DownloadInvoked(null, EventArgs.Empty);
}
catch { }
}
queueCheckHandler.Set();
//
}
public static void EndAddCourseFileData()
{
try
{
if (AfterDownloadInvoked != null)
AfterDownloadInvoked(null, EventArgs.Empty);
}
catch { }
}
/// <summary>
///
/// </summary>
/// <param name="Data"></param>
public static void RemoveCourseFileData(CourseFileData Data)
{
//
Data.RunningWorker.PauseDownload();
CourseFileDataManager.InitFileData(ref Data);
}
#endregion
#region
/// <summary>
///
/// </summary>
static void Update()
{
CourseFileData data;
workerHandles = new EventWaitHandle[workerWaitHandles.Count + 1];//.ToArray();
workerHandles[0] = addNewThreadWorkerHandler;
workerWaitHandles.CopyTo(workerHandles, 1);
try
{
while (true)
{
//
if (queue.Count == 0)
{
queueCheckHandler.Reset();
}
WaitHandle.WaitAll(entryWaitHandler);
//workers
int index = WaitHandle.WaitAny(workerHandles);
//
//workerHandler0
if (index == 0)
{
AddMoreThread();
workerHandles = new EventWaitHandle[workerWaitHandles.Count + 1];//.ToArray();
workerHandles[0] = addNewThreadWorkerHandler;
workerWaitHandles.CopyTo(workerHandles, 1);
continue;
}
//
//0
else
{
index--;
}
//ManulResetEvent
pauseCheckHandler.WaitOne();
//
//
if (currentThreadNumber > maxThreadNumber)
{
RemoveOneThread(index);
workerHandles = new EventWaitHandle[workerWaitHandles.Count + 1];//.ToArray();
workerHandles[0] = addNewThreadWorkerHandler;
workerWaitHandles.CopyTo(workerHandles, 1);
continue;
}
async.Post(doNothingCallback, null);
//
data = queue.Dequeue();
//
if (data.RunState != RunningStatue.RunRequest)
{
workerWaitHandles[index].Set();
continue;
}
else
{
workerWaitHandles[index].Reset();
}
//
CourseFileWorker worker = new CourseFileWorker(data);
workers[index].Worker = worker;
//
workers[index].HungryEvent.Set();
}
}
catch //(InvalidOperationException)
{
return;
}
}
/// <summary>
///
/// </summary>
public static void PauseDownloadEngine(bool StopTask)
{
//
stopCheckHandler.Reset();
pauseCheckHandler.Reset();
//
if (StopTask)
{
foreach (WorkerThread thread in workers)
{
if (thread.Worker != null)
{
thread.Worker.PauseDownload();
}
}
EventWaitHandle.WaitAll(workerWaitHandles.ToArray());
}
}
/// <summary>
///
/// </summary>
public static void ResumeDownloadEngine()
{
stopCheckHandler.Set();
pauseCheckHandler.Set();
}
/// <summary>
///
/// </summary>
static void AddMoreThread()
{
int newThreadCount = maxThreadNumber - currentThreadNumber;
if (newThreadCount < 0)
return;
lock (queue)
{
for (int i = 0; i < newThreadCount; i++)
{
WorkerThread newThread = new WorkerThread();
workers.Add(newThread);
workerWaitHandles.Add(newThread.WorkerEvent);
closeWaitHandles.Add(newThread.CloseEvent);
}
currentThreadNumber = maxThreadNumber;
addNewThreadWorkerHandler.Reset();
}
}
/// <summary>
///
/// </summary>
/// <param name="index"></param>
static void RemoveOneThread(int index)
{
lock (queue)
{
//
workers[index].Worker = null;
workers[index].Close();
//workerWaitHandler
workerWaitHandles.RemoveAt(index);
//closeWaitHandler
closeWaitHandles.RemoveAt(index);
//workers
workers.RemoveAt(index);
//
currentThreadNumber--;
}
}
/// <summary>
///
/// </summary>
/// <param name="ThreadNumber"></param>
public static void AlternateCurrentThread(int ThreadNumber)
{
if (ThreadNumber < 1 || ThreadNumber > 9)
return;
lock (queue)
{
maxThreadNumber = ThreadNumber;
//
//
if (currentThreadNumber < maxThreadNumber)
addNewThreadWorkerHandler.Set();
//
}
}
/// <summary>
///
/// </summary>
public static void CloseDownloadEngine()
{
//
async.OperationCompleted();
//
for (int i = 0; i < workers.Count; i++)
{
workers[i].Close();
}
WaitHandle.WaitAll(closeWaitHandles.ToArray());
for (int i = 0; i < workers.Count; i++)
{
workers[i].CloseEvent.Close();
workers[i].FinishedEvent.Close();
workers[i].HungryEvent.Close();
workers[i].WorkerEvent.Close();
}
//tp
}
#endregion
}
}
|