static void Main(string[] args)
        {
            Console.WriteLine("別スレッドで処理を行うクラスMyWorker");
            //引数で指定したメソッドを別スレッドで行うクラス
            var worker = new MyWorker <int, string>(Work);

            //結果を処理する完了イベントハンドラーを設定
            worker.Completed += result => Console.WriteLine(result);
            //処理を開始
            worker.Start(1);
            //待機中の処理
            while (!worker.IsCompleted)
            {
                Thread.Sleep(1000);
                if (!worker.IsCompleted)
                {
                    Console.WriteLine("...");
                }
            }
            Console.WriteLine("-----------------------------------");
            Console.WriteLine("MyWorkerをTask<T>でラップして実行");
            Task <string> task = DoWorkTask(10);

            while (!task.IsCompleted)
            {
                Task.Delay(1000).Wait();
                Console.WriteLine("...");
            }
            try
            {
                Console.WriteLine(task.GetAwaiter().GetResult());
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            Console.WriteLine("-----------------------------------");
            Console.WriteLine("例外をセットするサンプル");
            task = DoWorkTask(-1);
            while (!task.IsCompleted)
            {
                Task.Delay(1000).Wait();
                Console.WriteLine("...");
            }
            try
            {
                Console.WriteLine(task.GetAwaiter().GetResult());
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
        //完了通知のある非同期処理をラップしてTask<string>にする
        public static Task <string> DoWorkTask(int i)
        {
            var tcs    = new TaskCompletionSource <string>();
            var worker = new MyWorker <int, string>(Work);

            if (i >= 0)
            {
                worker.Completed += (result) =>
                {
                    //完了時に結果をセット
                    tcs.SetResult(result);
                };
                worker.Start(i);
            }
            else
            {
                //例外をセットすることもできる
                tcs.SetException(new ArgumentException());
            }
            return(tcs.Task);
        }