/// <summary>
        /// Matrix 연산 중에 현재 행보다 아래와 현재 열보다 오른쪽의 요소에 대해 작업을 Wavefront라 한다. 이를 병렬로 수행할 수 있도록 합니다.
        /// </summary>
        /// <param name="rows">매트릭스 행 수</param>
        /// <param name="cols">매트릭스 열 수</param>
        /// <param name="blocksPerRow">매트릭스 행 분할 수</param>
        /// <param name="blocksPerCol">매트릭스 열 분할 수</param>
        /// <param name="processBlock">매트릭스의 분할된 서브매트릭스를 처리할 델리게이트. processBlock(startRow, endRow, startCol, endCol);</param>
        public static void Wavefront(int rows, int cols, int blocksPerRow, int blocksPerCol, Action<int, int, int, int> processBlock) {
            rows.ShouldBePositive("rows");
            cols.ShouldBePositive("cols");
            processBlock.ShouldNotBeNull("processBlock");

            blocksPerRow.ShouldBeInRange(1, rows + 1, "blocksPerRow");
            blocksPerCol.ShouldBeInRange(1, cols + 1, "blocksPerCol");

            if(IsDebugEnabled)
                log.Debug("매트릭스의 블록 분할에 따른 Wavefront 작업을 수행합니다. rows=[{0}], cols=[{1}], blocksPerRow=[{2}], blocksPerCol=[{3}]",
                          rows, cols, blocksPerRow, blocksPerCol);

            int rowBlockSize = rows / blocksPerRow;
            int colBlockSize = cols / blocksPerCol;

            Wavefront(blocksPerRow,
                      blocksPerCol,
                      (r, c) => {
                          int startRow = r * rowBlockSize;
                          int endRow = (r < blocksPerRow - 1) ? startRow + rowBlockSize : rows;

                          int startCol = c * colBlockSize;
                          int endCol = (c < blocksPerCol - 1) ? startCol + colBlockSize : cols;

                          if(IsDebugEnabled)
                              log.Debug("매트릭스 서브 블럭 프로세싱... " +
                                        "r=[{0}], c=[{1}], rowBlockSize=[{2}], colBlockSize=[{3}], startRow=[{4}], endRow=[{5}], startCol=[{6}], endCol=[{7}]",
                                        r, c, rowBlockSize, colBlockSize, startRow, endRow, startCol, endCol);

                          processBlock(startRow, endRow, startCol, endCol);
                      });

            if(IsDebugEnabled)
                log.Debug("매트릭스의 블록 분할에 따른 모든 Wavefront 작업을 완료했습니다!!!");
        }
        /// <summary>
        /// 생성자
        /// </summary>
        /// <param name="initialCount">초기 countdown 수 (0보다 크거나 같아야 합니다)</param>
        /// <param name="action">countdown이 끝나면 (countdown 수가 0가 되면) 수행할 action</param>
        public ActionCountdownEvent(int initialCount, Action action) {
            initialCount.ShouldBePositiveOrZero("initialCount");
            action.ShouldNotBeNull("action");

            _action = action;
            _event = new CountdownEvent(initialCount);

            if(initialCount == 0)
                action();
            else
                _context = ExecutionContext.Capture();
        }
Exemple #3
0
        /// <summary>
        /// 지정된 delegate을 lock을 건 상태에서 실행합니다.
        /// </summary>
        /// <param name="runUnderLock">실행할 delegate</param>
        public void Execute(Action runUnderLock) {
            runUnderLock.ShouldNotBeNull("runUnderLock");

            var lockTaken = false;

            try {
                Enter(ref lockTaken);
                runUnderLock();
            }
            finally {
                if(lockTaken)
                    Exit();
            }
        }
Exemple #4
0
        public PeriodInvoker(string periodTimeFormat, TimeSpan idleTimeSpan, Action<object> periodAction, bool startNow = false) {
            periodAction.ShouldNotBeNull("periodAction");

            _periodAction = periodAction;
            _periodTimeFormat = periodTimeFormat;

            PeriodTimeSpan = idleTimeSpan;

            if(IsDebugEnabled)
                log.Debug("PeriodInvoke가 생성되었습니다. periodTimeFormat=[{0}], periodTimeSpan=[{1}], startNow=[{2}]", _periodTimeFormat,
                          _periodTimeFormat, startNow);

            if(startNow)
                Start();
        }
        /// <summary>
        /// 특정 수형의 특정 메소드를 호출할 수 있는 <see cref="MethodInvoker"/>를 입력 받아 <paramref name="action"/>을 수행합니다.
        /// </summary>
        /// <param name="instanceType"></param>
        /// <param name="action"></param>
        /// <param name="methodName"></param>
        /// <param name="parameterTypes"></param>
        public static void InvokeMethod(this Type instanceType, Action<MethodInvoker> action, string methodName,
                                        params Type[] parameterTypes) {
            instanceType.ShouldNotBeNull("instanceType");
            methodName.ShouldNotBeWhiteSpace("methodName");
            action.ShouldNotBeNull("action");

            var invoker = GetMethodInvoker(instanceType, methodName, parameterTypes);

            if(invoker != null) {
                if(IsDebugEnabled)
                    log.Debug("메소드[{0}]를 수행합니다...", methodName);

                action(invoker);
            }
        }
        /// <summary>
        /// 지정된 함수를 수행하는데 걸리는 시간 (msec)을 검사한다.
        /// </summary>
        /// <param name="gabageCollect">시간측정을 더 정밀하게 하기 위해 GabageCollect()를 수행하고 할 것인가?</param>
        /// <param name="action">시간 측정이 필요한 함수</param>
        /// <returns>지정된 함수 수행 시간 (milliseconds)</returns>
        /// <example>
        /// <code>
        /// int msec = With.OperationTime(false,
        ///			   delegate 
        ///            {
        ///                // some code...
        ///            });
        /// </code>
        /// </example>
        public static double OperationTimer(Action action, bool gabageCollect = false) {
            action.ShouldNotBeNull("action");

            if(gabageCollect)
                GabageCollect();

            var stopwatch = new Stopwatch();

            try {
                stopwatch.Start();

                action();
            }
            finally {
                stopwatch.Stop();
            }

            return stopwatch.ElapsedMilliseconds;
        }
        /// <summary>
        /// 특정 수형의 특정 메소드를 호출할 수 있는 <see cref="MethodInvoker"/>를 입력 받아 <paramref name="action"/>을 수행합니다.
        /// </summary>
        /// <param name="instanceType"></param>
        /// <param name="fromInclusive"></param>
        /// <param name="toExclusive"></param>
        /// <param name="action"></param>
        /// <param name="methodName"></param>
        /// <param name="parameterTypes"></param>
        public static ParallelLoopResult InvokeMethodAsParallel(this Type instanceType,
                                                                int fromInclusive,
                                                                int toExclusive,
                                                                Action<int, MethodInvoker> action,
                                                                string methodName,
                                                                params Type[] parameterTypes) {
            instanceType.ShouldNotBeNull("instanceType");
            action.ShouldNotBeNull("action");

            var methodInvoker = instanceType.GetMethodInvoker(methodName, DefaultFlags, parameterTypes);

            if(methodInvoker != null) {
                if(IsDebugEnabled)
                    log.Debug("메소드[{0}]를 병렬 방식으로 수행합니다...", methodName);

                return
                    Parallel.For(fromInclusive,
                                 toExclusive,
                                 i => action(i, methodInvoker));
            }

            return new ParallelLoopResult();
        }
Exemple #8
0
        /// <summary>
        /// 반복 주기에 따라 지정된 Action을 비동기 방식으로 작업을 수행합니다.
        /// </summary>
        /// <param name="periodTimeFormat">주기 표현식</param>
        /// <param name="idleTimeSpan">유휴 시간 간격</param>
        /// <param name="periodAction">주기 도래시 수행할 델리게이트</param>
        /// <param name="token">취소시 필요한 토큰</param>
        protected virtual void DoInvokeByPeriodTime(string periodTimeFormat, TimeSpan idleTimeSpan, Action<object> periodAction,
                                                    CancellationToken token) {
            periodAction.ShouldNotBeNull("periodAction");

            if(IsDebugEnabled)
                log.Debug("반복 주기에 따라 지정된 Action을 비동기 방식으로 수행하는 작업을 시작합니다... periodTimeFormat=[{0}]", periodTimeFormat);

            var previousTime = DateTime.MinValue;

            while(token.IsCancellationRequested == false) {
                var currentTime = DateTime.Now;

                if(PeriodTimeFormat.IsExpired(periodTimeFormat, previousTime, currentTime)) {
                    if(IsDebugEnabled)
                        log.Debug("반복 주기에 도래하여, 지정된 Action을 수행을 시작합니다... " +
                                  "periodTimeFormat=[{0}], previousTime=[{1}], currentTime=[{2}]",
                                  periodTimeFormat, periodAction, currentTime);

                    With.TryActionAsync(
                        () => Task.Factory.StartNew(periodAction, token, TaskCreationOptions.PreferFairness).Wait(token),
                        age => {
                            if(IsDebugEnabled)
                                log.Debug("작업 실행 중에 중단 요청에 의해 실행 취소되었습니다...");

                            age.Handle(ex => token.IsCancellationRequested);
                        });

                    previousTime = currentTime;

                    if(IsDebugEnabled)
                        log.Debug("반복 주기에 도래하여, 지정된 Action을 수행을 완료하였습니다!!! " +
                                  "periodTimeFormat=[{0}], previousTime=[{1}], currentTime=[{2}]",
                                  periodTimeFormat, periodAction, DateTime.Now);
                }

                if(token.IsCancellationRequested == false)
                    token.WaitHandle.WaitOne(idleTimeSpan);
            }
        }
Exemple #9
0
        /// <summary>
        /// 지정된 Action 들을 하나의 Transaction Scope로 묶어서 처리합니다.
        /// </summary>
        /// <param name="actionToExecute">실행할 Action</param>
        /// <example>
        ///	<code>
        ///		// 한 Tx안에서 3개의 Action 를 수행합니다.
        ///		With.TransactionScope(TransactionScopeOption.Required,
        ///                           System.Transactions.IsolationLevel.ReadCommited,
        ///                           FindAll_By_DetachedCriteria, 
        ///                           FindAll_By_Criterion, 
        ///                           FindAll_By_Example);
        /// </code>
        /// </example>
        public static void TransactionScope(Action actionToExecute) {
            actionToExecute.ShouldNotBeNull("actionToExecute");

            using(var txScope = AdoTool.CreateTransactionScope()) {
                actionToExecute();
                txScope.Complete();
            }
        }
Exemple #10
0
 /// <summary>
 /// 생성자
 /// </summary>
 /// <param name="action">dispose 시에 수행할 action</param>
 public DisposableAction(Action action) {
     action.ShouldNotBeNull("action");
     Action = action;
 }
Exemple #11
0
        private static Task<bool> SendTaskInternal(SmtpClient client, CancellationToken token, object userToken,
                                                   Action<TaskCompletionSource<bool>> sendAsyncAction) {
            client.ShouldNotBeNull("client");
            sendAsyncAction.ShouldNotBeNull("sendAsyncAction");

            if(IsDebugEnabled)
                log.Debug("SmtpClient를 이용하여 비동기방식으로 메일을 발송합니다... SmtpHost=[{0}]", client.Host);

            var tcs = new TaskCompletionSource<bool>(userToken);
            token.Register(client.SendAsyncCancel);

            SendCompletedEventHandler handler = null;
            handler = (s, e) => EventAsyncPattern.HandleCompletion(tcs,
                                                                   e,
                                                                   () => (e.Cancelled == false && e.Error != null),
                                                                   () => client.SendCompleted -= handler);
            client.SendCompleted += handler;

            try {
                sendAsyncAction(tcs);
            }
            catch(Exception ex) {
                client.SendCompleted -= handler;
                tcs.TrySetException(ex);
            }

            return tcs.Task;
        }
        /// <summary>
        /// 매트릭스에서 각 Cell의 연산을 Wavefront (물결)과 같이, 상위 Cell, 좌측 Cell의 작업이 완료한 후에, 작업하도록 합니다.
        /// </summary>
        /// <param name="rows">매트릭스 행 수</param>
        /// <param name="cols">매트릭스 열 수</param>
        /// <param name="processCell">매트릭스의 각 셀을 처리할 델리게이트</param>
        public static void Wavefront(int rows, int cols, Action<int, int> processCell) {
            rows.ShouldBePositive("rows");
            cols.ShouldBePositive("cols");
            processCell.ShouldNotBeNull("processCell");

            if(IsDebugEnabled)
                log.Debug("매트릭스 Wavefront 작업을 시작합니다. rows=[{0}], cols=[{1}]", rows, cols);

            try {
                // 현재 Cell의 상위 행 (r-1)의 열(column)별 작업 정보
                Task[] prevTaskRows = new Task[cols];
                // 현재 Cell의 바로 전 작업 (c-1)
                Task prevTaskInCurrentRow = null;
                // 현재 cell이 (r,c)일 때, (r-1, c), (r, c-1) 인 cell 의 작업을 나타낸다.
                var depedencies = new Task[2];

                for(var r = 0; r < rows; r++) {
                    prevTaskInCurrentRow = null;

                    for(var c = 0; c < cols; c++) {
                        int i = r, j = c;
                        Task currTask;

                        if(IsDebugEnabled)
                            log.Debug("매트릭스 Wavefront Task 정의 중... Matrix Cell({0},{1})", i, j);

                        if(r == 0 && c == 0) {
                            currTask = Task.Factory.StartNew(() => processCell(i, j));
                        }
                        else if(r == 0 || c == 0) {
                            // 전 작업
                            var antecedent = (c == 0) ? prevTaskRows[0] : prevTaskInCurrentRow;

                            currTask = antecedent.ContinueWith(p => {
                                                                   p.Wait(); // 예외 전파를 위해 필요할 뿐
                                                                   processCell(i, j);
                                                               },
                                                               TaskContinuationOptions.ExecuteSynchronously);
                        }
                        else {
                            depedencies[0] = prevTaskInCurrentRow; // 좌측 cell
                            depedencies[1] = prevTaskRows[c]; // 윗쪽 cell

                            currTask = Task.Factory.ContinueWhenAll(depedencies,
                                                                    ps => {
                                                                        Task.WaitAll(ps);
                                                                        processCell(i, j);
                                                                    },
                                                                    TaskContinuationOptions.ExecuteSynchronously);
                        }

                        if(IsDebugEnabled)
                            log.Debug("매트릭스 Wavefront Task 정의 완료!!! Matrix Cell({0},{1}), Task Id=[{2}]", i, j, currTask.Id);

                        prevTaskRows[c] = prevTaskInCurrentRow = currTask;
                    }
                }

                prevTaskInCurrentRow.Wait();
            }
            catch(AggregateException age) {
                if(log.IsErrorEnabled)
                    log.Error(age);

                age.Handle(ex => false);
            }

            if(IsDebugEnabled)
                log.Debug("매트릭스 Wavefront 작업이 완료되었습니다!!!");
        }
Exemple #13
0
        /// <summary>
        /// Internet Control Message Protocol (ICMP) echo message 를 비동기적으로 보냅니다.
        /// </summary>
        private static Task<PingReply> SendTaskCore(Ping ping, object userToken, Action<TaskCompletionSource<PingReply>> sendAsync) {
            ping.ShouldNotBeNull("ping");
            sendAsync.ShouldNotBeNull("sendAsync");

            if(IsDebugEnabled)
                log.Debug("Ping 작업을 비동기적으로 수행하는 Task를 생성합니다...");

            var tcs = new TaskCompletionSource<PingReply>(userToken);
            PingCompletedEventHandler handler = null;
            handler = (sender, e) => EventAsyncPattern.HandleCompletion(tcs, e, () => e.Reply, () => ping.PingCompleted -= handler);
            ping.PingCompleted += handler;

            try {
                sendAsync(tcs);
            }
            catch(Exception ex) {
                ping.PingCompleted -= handler;
                tcs.TrySetException(ex);
            }

            return tcs.Task;
        }
Exemple #14
0
        /// <summary>
        /// Matrix의 모든 요소를 <paramref name="action"/>에 인자로 넣어 실행합니다.
        /// </summary>
        /// <param name="m">matrix</param>
        /// <param name="action">실행할 delegate</param>
        public static void ForEach(this Matrix m, Action<double> action) {
            m.ShouldNotBeNull("m");
            action.ShouldNotBeNull("action");

            for(var r = 0; r < m.Rows; r++)
                for(var c = 0; c < m.Cols; c++)
                    action(m[r, c]);
        }
Exemple #15
0
        private static IEnumerable<Task> ReadIterator(Stream input, int bufferSize, Action<byte[], int> bufferAvailable) {
            input.ShouldNotBeNull("input");
            bufferSize.ShouldBePositive("bufferSize");
            bufferAvailable.ShouldNotBeNull("bufferAvailable");

            var buffer = new byte[bufferSize];

            while(true) {
                var readTask = input.ReadAsync(buffer, 0, buffer.Length);
                yield return readTask;

                if(readTask.Result <= 0)
                    break;

                bufferAvailable(buffer, readTask.Result);
            }
        }