利用Task加载DICOM的Study,Series,Image的类

这个类主要是利用了Task建立了一个一个工作列表,  
/********************************************************************   
created:        2013/01/21     
created:        21:1:2013   16:34    
use:          ThreadData study = new ThreadData();  
              study.SearchFlag = SearchThreadFlag.LocalDB;   
              study.Operation = GetStudy;        
              study.LevelFlag = LoadThreadFlag.Study;  
              study.Param = "study1";        
              actual = ThreadHelperSingleton.QueueUserWorkItem(ref study);        
              //call RunningTask.Result to Wait thread exit. It will block current thread.    
              bool isStudyOk = study.RunningTask.Result;

默认的Task Scheduler是FIFO(先进先出)。每次把要执行的Task加载到Queue里,然后顺序执行,每次执行前先根据优先级(比如Study〉Series〉Image)来对队列前面的Task进行Cancel,防止有些置前的Task因为计算量大而覆盖了后续Task的结果。
*********************************************************************/
 
//use this macro to enable/disable logger information.
//#define TaskLogger
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
 
namespace Commons
{
//Unit Test
    /// <summary>
        ///A test for CreateInstance
        ///</summary>
        public void CreateInstanceTest()
        {
            ThreadHelperSingleton actual;
            actual = ThreadHelperSingleton.CreateInstance();
        }
 
        /// <summary>
        ///A test for QueueUserWorkItem
        ///</summary>
        public void QueueUserWorkItemNormalTest()
        {
            bool actual;
 
            System.Diagnostics.Debug.WriteLine("Begin to run QueueUserWorkItemNormalTest, queue is (All,Worklist,LocalDB,Study1,Seies1,Image1,Study2,Image2,Seires2,Series3,Image3).");
 
            //Get All
            ThreadData all = new ThreadData();
            all.SearchFlag = SearchThreadFlag.All;
            all.Operation = GetAll;
            actual = ThreadHelperSingleton.QueueUserWorkItem(ref all);
            //bool isAllOk = all.RunningTask.Result;
 
            //Get Worklist
            ThreadData worklist = new ThreadData();
            worklist.SearchFlag = SearchThreadFlag.Worklist;
            worklist.Operation = GetWorklist;
            worklist.Param = "worklist1";
            actual = ThreadHelperSingleton.QueueUserWorkItem(ref worklist);
            //bool isWorklist = worklist.RunningTask.Result;
 
            //Get LocalDB
            ThreadData localDB = new ThreadData();
            localDB.SearchFlag = SearchThreadFlag.LocalDB;
            localDB.Operation = GetLocalDB;
            localDB.LevelFlag = LoadThreadFlag.All;
            localDB.Param = "local db";
            actual = ThreadHelperSingleton.QueueUserWorkItem(ref localDB);
            //bool isLocalDB = localDB.RunningTask.Result;
 
            //Get Study
            ThreadData study = new ThreadData();
            study.SearchFlag = SearchThreadFlag.LocalDB;
            study.Operation = GetStudy;
            study.LevelFlag = LoadThreadFlag.Study;
            study.Param = "study1";
            actual = ThreadHelperSingleton.QueueUserWorkItem(ref study);
            //bool isStudyOk = study.RunningTask.Result;
 
            //Get Series
            ThreadData series = new ThreadData();
            series.SearchFlag = SearchThreadFlag.LocalDB;
            series.Operation = GetSeries;
            series.LevelFlag = LoadThreadFlag.Series;
            series.Param = "series1";
            actual = ThreadHelperSingleton.QueueUserWorkItem(ref series);
            //bool isSeriesOk = series.RunningTask.Result;
 
            //Get Image
            ThreadData image = new ThreadData();
            image.SearchFlag = SearchThreadFlag.LocalDB;
            image.Operation = GetImage;
            image.LevelFlag = LoadThreadFlag.Image;
            image.Param = "image1";
            actual = ThreadHelperSingleton.QueueUserWorkItem(ref image);
            //bool isLoadImageOK = image.RunningTask.Result;
 
            //Get Study2
            ThreadData study2 = new ThreadData();
            study2.SearchFlag = SearchThreadFlag.LocalDB;
            study2.Operation = GetStudy;
            study2.LevelFlag = LoadThreadFlag.Study;
            study2.Param = "study2";
            actual = ThreadHelperSingleton.QueueUserWorkItem(ref study2);
            //bool isStudyOk2 = study2.RunningTask.Result;
 
            //Get Image2
            ThreadData image2 = new ThreadData();
            image2.SearchFlag = SearchThreadFlag.LocalDB;
            image2.Operation = GetImage;
            image2.LevelFlag = LoadThreadFlag.Image;
            image2.Param = "image2";
            actual = ThreadHelperSingleton.QueueUserWorkItem(ref image2);
            //bool isLoadImageOK2 = image2.RunningTask.Result;
 
            //Get Series2
            ThreadData series2 = new ThreadData();
            series2.SearchFlag = SearchThreadFlag.LocalDB;
            series2.Operation = GetSeries;
            series2.LevelFlag = LoadThreadFlag.Series;
            series2.Param = "series2";
            actual = ThreadHelperSingleton.QueueUserWorkItem(ref series2);
            //bool isSeriesOk2 = series2.RunningTask.Result;
 
            //Get Series3
            ThreadData series3 = new ThreadData();
            series3.SearchFlag = SearchThreadFlag.LocalDB;
            series3.Operation = GetSeries;
            series3.LevelFlag = LoadThreadFlag.Series;
            series3.Param = "series3";
            actual = ThreadHelperSingleton.QueueUserWorkItem(ref series3);
            //bool isSeriesOk3 = series3.RunningTask.Result;
 
            //Get Image3
            ThreadData image3 = new ThreadData();
            image3.SearchFlag = SearchThreadFlag.LocalDB;
            image3.Operation = GetImage;
            image3.LevelFlag = LoadThreadFlag.Image;
            image3.Param = "image3";
            actual = ThreadHelperSingleton.QueueUserWorkItem(ref image3);
            //bool isLoadImageOK3= image3.RunningTask.Result;
 
            System.Diagnostics.Debug.WriteLine("QueueUserWorkItemNormalTest run successfully.");
        }
 
        private bool GetStudy(object study)
        {
            Random rand = new Random();
            Thread.Sleep(rand.Next(100));
 
            System.Diagnostics.Debug.WriteLine("Get study successfully. " + (study ?? "") + DateTime.Now.ToString(" yyyy-MM-dd HH:mm:ss.f"));
            return true;
        }
 
        private bool GetSeries(object series)
        {
            Random rand = new Random();
            Thread.Sleep(rand.Next(100));
 
            System.Diagnostics.Debug.WriteLine("Get series successfully. " + (series ?? "") + DateTime.Now.ToString(" yyyy-MM-dd HH:mm:ss.f"));
            return true;
        }
 
        private bool GetImage(object image)
        {
            Random rand = new Random();
            Thread.Sleep(rand.Next(100));
 
            System.Diagnostics.Debug.WriteLine("Get image successfully. " + (image ?? "") + DateTime.Now.ToString(" yyyy-MM-dd HH:mm:ss.f"));
            return true;
        }
 
        private bool GetWorklist(object worklist)
        {
            Random rand = new Random();
            Thread.Sleep(rand.Next(100));
 
            System.Diagnostics.Debug.WriteLine("Get worklist successfully. " + (worklist ?? "") + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.f"));
            return true;
        }
 
        private bool GetLocalDB(object database)
        {
            Random rand = new Random();
            Thread.Sleep(rand.Next(100));
 
            GetStudy(database.ToString() + "'s Study");
            GetSeries(database.ToString() + "'s Series");
            GetImage(database.ToString() + "'s Image");
 
            System.Diagnostics.Debug.WriteLine("Get database successfully. " + (database ?? "") + DateTime.Now.ToString(" yyyy-MM-dd HH:mm:ss.f"));
 
            return true;
        }
 
        private bool GetAll(object all)
        {
            Random rand = new Random();
            Thread.Sleep(rand.Next(100));
 
            GetWorklist("all worklist");
            GetLocalDB("all database");
 
            System.Diagnostics.Debug.WriteLine("Get All successfully. " + (all ?? "") + DateTime.Now.ToString(" yyyy-MM-dd HH:mm:ss.f"));
 
            return true;
        }
    public enum SearchThreadFlag
    {
        LocalDB = 0,
        Worklist = 1,
        All = 2,
    }
 
    public enum LoadThreadFlag
    {
        None = 0,
        Study = 1,
        Series = 2,
        Rawdata = 3,
        Report = 4,
        Image = 5,
        All = 6,
    }
 public class ThreadData
    {
        public SearchThreadFlag SearchFlag { get; set; }
        public LoadThreadFlag LevelFlag { get; set; }
        public Func<object, bool> Operation { get; set; }
        public Action Callback {get; set; }
        public object Param { get; set; }
        public CancellationTokenSource CancelHandler { get; internal set; }
        public Task<bool> RunningTask { get; internal set; }
    }
 
    public class ThreadHelperSingleton
    {
        public static Dictionary<ThreadData, Task<bool>> TaskPool { get; internal set; }
 
        private static ThreadHelperSingleton instance;
 
        private ThreadHelperSingleton()
        {
 
        }
 
        public static ThreadHelperSingleton CreateInstance()
        {
            if (null == instance)
            {
                instance = new ThreadHelperSingleton();
            }
 
            return instance;
        }
 
        public static bool QueueUserWorkItem(ref ThreadData data)
        {
            if (null == data)
            {
                data = null;
                return false;
            }
 
            if (null == data.Operation)
            {
                data = null;
                return false;
            }
 
#if TaskLogger
            System.Diagnostics.Debug.WriteLine("(QueueUserWorkItem)Begin to QueueUserWorkItem." + " SearchFlag is " + data.SearchFlag + ", LevelFlag is " + data.LevelFlag);#endif
 
#if TaskLogger
            System.Diagnostics.Debug.WriteLine("(QueueUserWorkItem)Before StartThread, TaskPool's count is " + TaskPool.Count);#endif
            //
            StopPreThread(data);
 
            //
            bool isOk = StartThread(data);
            if (!isOk)
            {
                data = null;
            }
 
#if TaskLogger
            System.Diagnostics.Debug.WriteLine("(QueueUserWorkItem)After StartThread, TaskPool's count is " + (TaskPool !=  null ? TaskPool.Count : 0));#endif
 
#if TaskLogger
            System.Diagnostics.Debug.WriteLine("(QueueUserWorkItem)End QueueUserWorkItem." + " SearchFlag is " + data.SearchFlag + ", LevelFlag is " + data.LevelFlag);#endif
 
            return isOk;
        }
 
     
     private static bool StartThread(ThreadData data)
        {
            if (null == data)
            {
                return false;
            }
 
            if (null == data.Operation)
            {
                return false;
            }
 
#if TaskLogger
            System.Diagnostics.Debug.WriteLine("(StartThread)Begin to StartThread.");#endif
 
            if (null == TaskPool
                || 0 == TaskPool.Count)
            {
                if (null == TaskPool)
                {
                    TaskPool = new Dictionary<ThreadData, Task<bool>>();
                }
 
#if TaskLogger
                System.Diagnostics.Debug.WriteLine("(StartThread)TaskPool is empty, directly to add new task.");#endif
 
                StartNewTask(data);
            }
            else
            {
                if (data.SearchFlag.Equals(SearchThreadFlag.All))
                {
#if TaskLogger
                    System.Diagnostics.Debug.WriteLine("(StartThread)SearchFlag is All, it not need to attach task to parent task.");#endif
 
                    StartNewTask(data);
                }
                else if (data.SearchFlag.Equals(SearchThreadFlag.Worklist))
                {
#if TaskLogger
                    System.Diagnostics.Debug.WriteLine("(StartThread)SearchFlag is worklist, it not need to attach task to parent task.");#endif
 
                    StartNewTask(data);
                }
                else if (data.SearchFlag.Equals(SearchThreadFlag.LocalDB))
                {
#if TaskLogger
                    System.Diagnostics.Debug.WriteLine("(StartThread)SearchFlag is localDB, begin to start new task by level flag.");#endif
                    //Current we use synchronized rule to load data, so it not need  attach sub task to parent task. 
                    //We use StartNewTask to create a normal task.
 
                    //StartSubTask(data);
 
                    StartNewTask(data);
                }
                else
                {
#if TaskLogger
                    System.Diagnostics.Debug.WriteLine("(StartThread)SearchFlag is unknown, use StartNewTask to create default task.");#endif
 
                    StartNewTask(data);
                }
            }
 
#if TaskLogger
            System.Diagnostics.Debug.WriteLine("(StartThread)End StartThread.");#endif
 
            return true;
        }
 
        private static bool StopPreThread(ThreadData data)
        {
            if (null == data)
            {
                return false;
            }
 
            if (null == data.Operation)
            {
                return false;
            }
 
            if (null == TaskPool
                || 0 == TaskPool.Count)
            {
                return true;
            }
 
#if TaskLogger
            System.Diagnostics.Debug.WriteLine("(StopPreThread)Begin to StopPreThread");#endif
 
            IList<KeyValuePair<ThreadData, Task<bool>>> tasks = null;
 
            if (data.SearchFlag.Equals(SearchThreadFlag.All))
            {
#if TaskLogger
                System.Diagnostics.Debug.WriteLine("(StopPreThread)SearchFlag is All.");#endif
 
                tasks = TaskPool.ToList();
            }
            else if (data.SearchFlag.Equals(SearchThreadFlag.Worklist))
            {
#if TaskLogger
                System.Diagnostics.Debug.WriteLine("(StopPreThread)SearchFalg is Worklist.");#endif
 
                tasks = TaskPool.ToList();
            }
            else if (data.SearchFlag.Equals(SearchThreadFlag.LocalDB))
            {
#if TaskLogger
                System.Diagnostics.Debug.WriteLine("(StopPreThread)SearchFlag is LocalDB");#endif
 
                if (data.LevelFlag.Equals(LoadThreadFlag.All))
                {
#if TaskLogger
                    System.Diagnostics.Debug.WriteLine("LevelFlag is All.");#endif
 
                    tasks = TaskPool.ToList();
                }
                else if (data.LevelFlag.Equals(LoadThreadFlag.Study))
                {
#if TaskLogger
                    System.Diagnostics.Debug.WriteLine("(StopPreThread)LevelFlag is Study.");#endif
 
                    tasks = TaskPool.ToList();
                }
                else if (data.LevelFlag.Equals(LoadThreadFlag.Series))
                {
#if TaskLogger
                    System.Diagnostics.Debug.WriteLine("(StopPreThread)LevleFlag is Series.");#endif
 
                    tasks = TaskPool.Where(d =>
                     d.Key.SearchFlag.Equals(SearchThreadFlag.LocalDB)
                        && (d.Key.LevelFlag.Equals(LoadThreadFlag.Series)
                            || d.Key.LevelFlag.Equals(LoadThreadFlag.Image)
                            || d.Key.LevelFlag.Equals(LoadThreadFlag.All)
                            || d.Key.LevelFlag.Equals(LoadThreadFlag.None)
                            )
                     ).ToList();
                }
                else if (data.LevelFlag.Equals(LoadThreadFlag.Rawdata))
                {
#if TaskLogger
                    System.Diagnostics.Debug.WriteLine("(StopPreThread)LevleFlag is Rawdata.");#endif
 
                    tasks = TaskPool.Where(d =>
                     d.Key.SearchFlag.Equals(SearchThreadFlag.LocalDB)
                        && (d.Key.LevelFlag.Equals(LoadThreadFlag.Rawdata)
                            || d.Key.LevelFlag.Equals(LoadThreadFlag.All)
                            || d.Key.LevelFlag.Equals(LoadThreadFlag.None)
                            )
                     ).ToList();
                }
                else if (data.LevelFlag.Equals(LoadThreadFlag.Report))
                {
#if TaskLogger
                    System.Diagnostics.Debug.WriteLine("(StopPreThread)LevleFlag is Report.");#endif
 
                    tasks = TaskPool.Where(d =>
                     d.Key.SearchFlag.Equals(SearchThreadFlag.LocalDB)
                        && (d.Key.LevelFlag.Equals(LoadThreadFlag.Report)
                            || d.Key.LevelFlag.Equals(LoadThreadFlag.All)
                            || d.Key.LevelFlag.Equals(LoadThreadFlag.None)
                            )
                     ).ToList();
                }
                else if (data.LevelFlag.Equals(LoadThreadFlag.Image))
                {
                    tasks = TaskPool.Where(d =>
                        d.Key.SearchFlag.Equals(SearchThreadFlag.LocalDB)
                          && (d.Key.LevelFlag.Equals(LoadThreadFlag.Image)
                            || d.Key.LevelFlag.Equals(LoadThreadFlag.All)
                            || d.Key.LevelFlag.Equals(LoadThreadFlag.None)
                            )
                    ).ToList();
                }
                else
                {
#if TaskLogger
                    System.Diagnostics.Debug.WriteLine("(StopPreThread)SearchFlag is unknown, it will clear all Tasks.");#endif
                    tasks = TaskPool.ToList();
                }
            }
            else
            {
#if TaskLogger
                System.Diagnostics.Debug.WriteLine("(StopPreThread)SearchFlag is unknown, it will clear all Tasks.");#endif
                tasks = TaskPool.ToList();
            }
 
            if (null != tasks && 0 != tasks.Count)
            {
#if TaskLogger
                System.Diagnostics.Debug.WriteLine("(StopPreThread)Remove Task count is " + tasks.Count);#endif
 
                int count = tasks.Count;
 
                for (int i = 0; i < count; i++)
                {
#if TaskLooger
                    System.Diagnostics.Debug.WriteLine("(StopPreThread)Cancel task id is " + tasks[i].Value.Id + ", SearchFlag is " + tasks[i].Key.SearchFlag + ", LevelFlag is " + tasks[i].Key.LevelFlag);#endif
 
                    if (null != tasks[i].Key.CancelHandler)
                    {
                        tasks[i].Key.CancelHandler.Cancel();
                    }
 
                    TaskPool.Remove(tasks[i].Key);
 
                    tasks[i].Key.RunningTask = null;
                }
 
#if TaskLogger
                System.Diagnostics.Debug.WriteLine("(StopPreThread)Remove Task finished.");#endif
            }
 
#if TaskLogger
            System.Diagnostics.Debug.WriteLine("(StopPreThread)End StopPreThread.");#endif
 
            return true;
        }
 
        private static bool StartNewTask(ThreadData data)
        {
            if (null == data
                || null == data.Operation)
            {
                return false;
            }
 
#if TaskLogger
            System.Diagnostics.Debug.WriteLine("(StartNewTask)Begin to start new task.");#endif
 
            var tokenSource = new CancellationTokenSource();
 
            Task<bool> task = Task<bool>.Factory.StartNew(data.Operation, data.Param, tokenSource.Token);
            
            if (null != task && null != data.Callback)
            {
                task.ContinueWith(t => { var exp = t.Exception; }, TaskContinuationOptions.OnlyOnFaulted)
                    .ContinueWith(delegate { data.Callback(); })
                    .ContinueWith(t => { var exp = t.Exception; }, TaskContinuationOptions.OnlyOnFaulted);
            }
 
            data.CancelHandler = tokenSource;
            data.RunningTask = task;
 
            if (null != task)
            {
                TaskPool.Add(data, task);
 
#if TaskLogger
                System.Diagnostics.Debug.WriteLine("(StartNewTask)Add task to TaskPool, id is " + task.Id + ", SearchFlag " + data.SearchFlag + ", LevelFlag " + data.LevelFlag);                System.Diagnostics.Debug.WriteLine("(StartNewTask)End StartNewTask");#endif
 
                return true;
            }
 
#if TaskLogger
            System.Diagnostics.Debug.WriteLine("(StartNewTask)End StartNewTask");#endif
 
            return false;
        }
        private static bool StartSubTask(ThreadData data)
        {
            if (null == data
                || null == data.Operation)
            {
                return false;
            }
 
#if TaskLogger
            System.Diagnostics.Debug.WriteLine("(StartSubTask)Begin to StartSubTask");#endif
 
            KeyValuePair<ThreadData, Task<bool>> parentTask = new KeyValuePair<ThreadData, Task<bool>>();
 
            if (data.LevelFlag.Equals(LoadThreadFlag.All))
            {
#if TaskLogger
                System.Diagnostics.Debug.WriteLine("(StartSubTask)LevelFlag is All, it not need to attach task to parent task.");#endif
 
                StartNewTask(data);
            }
            else if (data.LevelFlag.Equals(LoadThreadFlag.Study))
            {
#if TaskLogger
                System.Diagnostics.Debug.WriteLine("(StartSubTask)LevelFlag is Study, it not need to attach task to parent task.");#endif
 
                StartNewTask(data);
            }
            else
            {
                if (data.LevelFlag.Equals(LoadThreadFlag.Series))
                {
#if TaskLogger
                    System.Diagnostics.Debug.WriteLine("(StartSubTask)LevelFlag is Series.");#endif
 
                    parentTask = TaskPool.Where(t =>
                        t.Key.LevelFlag.Equals(LoadThreadFlag.Study)
                    ).FirstOrDefault();
                }
                else if (data.LevelFlag.Equals(LoadThreadFlag.Image))
                {
#if TaskLogger
                    System.Diagnostics.Debug.WriteLine("(StartSubTask)LevelFlag is Image.");#endif
 
                    parentTask = TaskPool.Where(t =>
                        t.Key.LevelFlag.Equals(LoadThreadFlag.Series)
                    ).FirstOrDefault();
                }
 
                //Create child task.
                if (null != parentTask.Value
                    && !parentTask.Value.Status.Equals(TaskStatus.RanToCompletion)
                    && !parentTask.Value.Status.Equals(TaskStatus.Canceled)
                    && !parentTask.Value.Status.Equals(TaskStatus.Faulted))
                {
#if TaskLogger
                    System.Diagnostics.Debug.WriteLine("(StartSubTask)Start to attach sub task to parent task.");#endif
 
                    var subTask = parentTask.Value.ContinueWith(
                        delegate { return data.Operation(data.Param); },
                        parentTask.Key.CancelHandler.Token,
                        TaskContinuationOptions.OnlyOnRanToCompletion,
                        TaskScheduler.Default
                        );
 
                    //parentTask.Value.Start();
 
                    data.CancelHandler = parentTask.Key.CancelHandler;
                    data.RunningTask = subTask;
 
                    TaskPool.Add(data, subTask);
 
#if TaskLogger
                    System.Diagnostics.Debug.WriteLine("(StartSubTask)Add task to TaskPool, id is " + subTask.Id + ", SearchFlag " + data.SearchFlag + ", LevelFlag " + data.LevelFlag);#endif
                }
                else
                {
                    StartNewTask(data);
                }
            }
 
#if TaskLogger
            System.Diagnostics.Debug.WriteLine("(StartSubTask)End StartSubTask");#endif
 
            return true;
        }
 
    }
}

你可能感兴趣的:(利用Task加载DICOM的Study,Series,Image的类)