/// <summary> /// Create an object of type <paramref name="objectType"/> when the type is only known during runtime. /// </summary> /// <param name="objectType"></param> /// <returns></returns> public object Create(Type objectType) { if (Logger != null) { Logger.Trace("Attempting to create object of type " + objectType.Name); } if (!CreationMapping.ContainsKey(objectType)) { throw new InvalidOperationException("There is no method to create this type!"); } return(CreationMapping[objectType].Invoke(this)); }
protected async Task ExecuteWhenReady_Generic(Action job, bool block = false) { var jobID = Guid.NewGuid(); Logger.Trace($"Running job on async queue (blocking: {block}). ID: {jobID}"); AutoResetEvent myEvent = new AutoResetEvent(false); AutoResetEvent currentJobEvent = default(AutoResetEvent); //Grab the next signaler and add us as the last job lock (QueueLock) { if (JobQueue.Count == 0) { Logger.Trace($"0 jobs in queue, so using a new reset event. It should instantly start"); currentJobEvent = new AutoResetEvent(true); } else { Logger.Trace($"{JobQueue.Count} jobs in queue, so using an existing reset event. It should start when all other jobs are finished."); currentJobEvent = JobQueue.Last().Item2; } JobQueue.Enqueue(Tuple.Create(job, myEvent)); } //Wait for our turn Logger.Debug($"Waiting for turn for job {jobID}"); if (block) { currentJobEvent.WaitOne(); } else { await Task.Run(() => currentJobEvent.WaitOne()); } try { //Run our crap Logger.Debug($"Beginning enqueued job: {jobID}"); job.Invoke(); Logger.Debug($"Completed job: {jobID}"); } finally { //Remove ourselves from the queue FIRST, that way if we're the only thing in the queue and a new //job gets added, it will either attach to our event which HASN'T been set yet, or it'll see //nothing in the queue and not have any wait. lock (QueueLock) { var dequeuedJob = JobQueue.Dequeue(); if (!object.ReferenceEquals(dequeuedJob.Item1, job)) { throw new InvalidOperationException("The queue had a programming failure; the dequeued job is not the same as the one that just completed!"); } } //Tell the next person in line to go. myEvent.Set(); } }