예제 #1
0
        public BackgroundDispatcherAsync(
            [NotNull] IBackgroundExecution execution,
            [NotNull] Func <Guid, object, Task> action,
            [CanBeNull] object state,
            [NotNull] TaskScheduler taskScheduler,
            int maxConcurrency,
            bool ownsScheduler)
        {
            if (maxConcurrency <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(maxConcurrency));
            }

            _execution     = execution ?? throw new ArgumentNullException(nameof(execution));
            _action        = action ?? throw new ArgumentNullException(nameof(action));
            _state         = state;
            _taskScheduler = taskScheduler ?? throw new ArgumentNullException(nameof(taskScheduler));
            _ownsScheduler = ownsScheduler;

#if !NETSTANDARD1_3
            AppDomainUnloadMonitor.EnsureInitialized();
#endif

            _stopped = new CountdownEvent(maxConcurrency);

            for (var i = 0; i < maxConcurrency; i++)
            {
                Task.Factory.StartNew(
                    DispatchLoop,
                    CancellationToken.None,
                    TaskCreationOptions.None,
                    _taskScheduler).Unwrap();
            }
        }
예제 #2
0
        public BackgroundExecution(CancellationToken stopToken, [NotNull] BackgroundExecutionOptions options)
        {
            _options = options ?? throw new ArgumentNullException(nameof(options));

            _logger    = LogProvider.GetLogger(GetType());
            _createdAt = Stopwatch.StartNew();

            _stopToken = stopToken;

            _stopRegistration = _stopToken.Register(SetStoppedAt);

#if !NETSTANDARD1_3
            AppDomainUnloadMonitor.EnsureInitialized();
#endif
        }
예제 #3
0
        /// <summary>Initializes a new instance of the <see cref="BackgroundTaskScheduler"/>
        /// class with the specified <paramref name="threadFactory"/> and an optional exception
        /// handler. All the created threads will be started to dispatch <see cref="Task"/>
        /// instances scheduled to run on this scheduler.</summary>
        /// <param name="threadFactory">Callback that creates one or more dedicated threads.</param>
        /// <param name="exceptionHandler">Optional callback that is invoked when unhandled exception occurs
        /// in one of the threads. After this event this instance is considered stopped.</param>
        /// <exception cref="ArgumentNullException"><paramref name="threadFactory"/> is <see langword="null"/>.</exception>
        /// <exception cref="ArgumentException"><paramref name="threadFactory"/> returned <see langword="null"/> or zero threads.</exception>
        /// <exception cref="ArgumentException"><paramref name="threadFactory"/> returned at least one thread not in the <see cref="ThreadState.Unstarted"/> state.</exception>
        public BackgroundTaskScheduler(
            [NotNull] Func <ThreadStart, IEnumerable <Thread> > threadFactory,
            [CanBeNull] Action <Exception> exceptionHandler)
        {
            if (threadFactory == null)
            {
                throw new ArgumentNullException(nameof(threadFactory));
            }

            _exceptionHandler = exceptionHandler;
            _semaphore        = new Semaphore(0, Int32.MaxValue);

            // Stopped event should always be the first in this array, see the DispatchLoop method.
            _waitHandles = new WaitHandle[] { _stopped, _semaphore };

#if !NETSTANDARD1_3
            AppDomainUnloadMonitor.EnsureInitialized();
#endif

            _threads = threadFactory(DispatchLoop)?.ToArray();

            if (_threads == null || _threads.Length == 0)
            {
                throw new ArgumentException("At least one non-started thread should be created.", nameof(threadFactory));
            }

            if (_threads.Any(thread => thread == null || (thread.ThreadState & ThreadState.Unstarted) == 0))
            {
                throw new ArgumentException("All the threads should be non-null and in the ThreadState.Unstarted state.", nameof(threadFactory));
            }

            foreach (var thread in _threads)
            {
                thread.Start();
            }

            _ourThreadIds = new HashSet <int>(_threads.Select(x => x.ManagedThreadId));
        }
예제 #4
0
        public BackgroundDispatcher(
            [NotNull] IBackgroundExecution execution,
            [NotNull] Action <Guid, object> action,
            [CanBeNull] object state,
            [NotNull] Func <ThreadStart, IEnumerable <Thread> > threadFactory)
        {
            if (threadFactory == null)
            {
                throw new ArgumentNullException(nameof(threadFactory));
            }

            _execution = execution ?? throw new ArgumentNullException(nameof(execution));
            _action    = action ?? throw new ArgumentNullException(nameof(action));
            _state     = state;

#if !NETSTANDARD1_3
            AppDomainUnloadMonitor.EnsureInitialized();
#endif

            var threads = threadFactory(DispatchLoop)?.ToArray();

            if (threads == null || threads.Length == 0)
            {
                throw new ArgumentException("At least one unstarted thread should be created.", nameof(threadFactory));
            }

            if (threads.Any(thread => thread == null || (thread.ThreadState & ThreadState.Unstarted) == 0))
            {
                throw new ArgumentException("All the threads should be non-null and in the ThreadState.Unstarted state.", nameof(threadFactory));
            }

            _stopped = new CountdownEvent(threads.Length);

            foreach (var thread in threads)
            {
                thread.Start();
            }
        }