Esempio n. 1
0
        /// <summary>
        /// Assigns work to a free worker.
        /// If there is no free workers will block the thread until one becomes availiable or the specified time elapses.
        /// </summary>
        /// <param name="data">The data to be used by the worker</param>
        /// <param name="timeout">The number of milliseconds to wait for a worker to become availiable.
        /// Use zero to return immediately. Use -1 to wait indefinitely.</param>
        /// <returns>true if the work was assigned, false otherwise</returns>
        protected bool AssignWorkWait(TWorkerData data, int timeout)
        {
            Worker worker;
            WorkerTaskObject <TManagerData, TManagerResult, TWorkerData, TWorkerResult> taskObject;

            if (abortRequested || cancelRequested)
            {
                return(false);
            }

            // 1. Assure only the Manager Thread access this method
            if ((this.managerThread == null) || (this.managerThread.ManagedThreadId != Thread.CurrentThread.ManagedThreadId))
            {
                throw new AccessViolationException("Only Manager Thread can access this method");
            }

            // 2. Wait for a worker to be released, or timeout elapses.
            // This doesn't guarantee that only one thread will cross the synchronization event so
            // in principle many threads can reach the lock and the Q may be empty while dequeuing.
            // However, this will never happen because previously we limited the access to this function
            // to the Manager thread.
            if (!this.availiableWorker.WaitOne(timeout))
            {
                return(false);
            }

            // 3. Acquire Lock. Synchronized access to the idleWorker queue and busyWorkers list.
            this.workersLock.AcquireWriterLock(-1);
            Thread.BeginCriticalRegion();

            // 4. Get a worker from the idleWorkers queue.
            // Main thread can not reach this point if the availiableWorker event was not set
            // which occurs only at initialization or when a woker is released
            worker = this.idleWorkers.Dequeue();
            // 5. Update availiableWorker synchronization event
            // Notice that availiableWorker event is only set/reset within the workersLock context
            if (idleWorkers.Count > 0)
            {
                this.availiableWorker.Set();
            }
            else
            {
                this.availiableWorker.Reset();
            }
            // 6. Reset allWorkersFree synchronization event
            // Notice that allWorkersFree event is only set/reset within the workersLock context
            this.allWorkersFree.Reset();
            // 7. Add the worker to the busyWorkers list in its corresponding position
            this.busyWorkers.Insert(worker.WorkerNumber, worker);
            // 8. Release the lock
            this.workersLock.ReleaseWriterLock();
            Thread.EndCriticalRegion();

            // 9. Create the data object to be passed to the worker
            taskObject = new WorkerTaskObject <TManagerData, TManagerResult, TWorkerData, TWorkerResult>(worker, data);
            // 10. Start the worker
            worker.DoWork(taskObject);

            return(true);
        }
Esempio n. 2
0
 /// <summary>
 /// Performs the worker task by calling the Owner.WorkerTask method.
 /// When it completes, enqueues the worker in the Owner.idleWorkers queue.
 /// </summary>
 /// <param name="o">Object that contains the task data to be used during the worker execution</param>
 private void WorkerThreadTask(object o)
 {
     try
     {
         WorkerTaskObject <TManagerData, TManagerResult, TWorkerData, TWorkerResult> taskObject =
             o as WorkerTaskObject <TManagerData, TManagerResult, TWorkerData, TWorkerResult>;
         if (taskObject == null)
         {
             return;
         }
         owner.WorkerTask(taskObject);
     }
     catch
     {
         // Nothing to do here, just ensure the finally block will be executed
     }
     finally
     {
         owner.FreeWorker(this);
     }
 }
Esempio n. 3
0
 /// <summary>
 /// Configures the thread and begins the execution of the Owner.WorkerTask method.
 /// </summary>
 /// <param name="taskObject">Object that contains the task data to be used during the worker execution</param>
 public void DoWork(WorkerTaskObject <TManagerData, TManagerResult, TWorkerData, TWorkerResult> taskObject)
 {
     this.workerThread = new Thread(this.workerThreadTask);
     this.workerThread.IsBackground = this.runInBackground;
     this.workerThread.Start(taskObject);
 }
Esempio n. 4
0
 /// <summary>
 /// When overriden in a derived class, performs the worker task
 /// </summary>
 /// <param name="taskObject">Object that contains the task data with which execute the task</param>
 protected abstract TWorkerResult WorkerTask(WorkerTaskObject <TManagerData, TManagerResult, TWorkerData, TWorkerResult> taskObject);