public void LoadForms(bool lazyLoading, Func<Form, bool> predicate)
{
if (context.AsyncFromLoadingMaxWorkers < 1)
throw new InvalidOperationException("AsyncFromLoadingMaxWorkers cannot be less than 1");
Stream stream = context.DataFileProvider.GetDataFile(FileMode.Open, fileName).Open();
// Uncomment this to preload a whole file into memory
// The loading time is marginaly shorter (around 4%)
// but only when another background worker is employed
//Log.Fine("Preloading plugin file {0}.", fileName);
//var data = new byte[stream.Length];
//stream.Read(data, 0, (int)stream.Length);
//stream = new ReadOnlyMemoryStream(data);
using (var reader = context.CreateReader(stream))
{
// Header needs to be read again
header = reader.ReadHeader();
// Prepare reference mapper
reader.ReferenceMapper = new PluginReferenceMapper(this);
// Prepare string locator (if plugin strings are localized)
if (reader.PluginFlags.HasFlag(PluginFlags.Localized))
reader.StringLocator = new PluginStringLocator(this);
int formsToLoadCount = 0;
// Apply predicate to the enumeration, if any
// this will cause the total number of forms to load be unknown
var formsToLoadEnumeration = context.Forms.OfPlugin(this);
if (predicate != null)
{
// TODO: Fix the list to make the total count known
formsToLoadEnumeration = formsToLoadEnumeration.Where(predicate);
formsToLoadCount = formsToLoadEnumeration.Count();
}
else
{
// Get count if enumeration is a list or a collection
formsToLoadCount = formsToLoadEnumeration.Count();
}
if (formsToLoadEnumeration.Any())
{
var formsToLoad = formsToLoadEnumeration;
int formsToLoadCountAtLeast = 0;
// Determine number of background jobs, if any
int jobs = 0;
if (context.AsyncFormLoading)
{
// Materialize part of the list
// to determine the count of background jobs at least
if (formsToLoadCount == 0)
{
int take = context.AsyncFormLoadingWorkerThreshold * context.AsyncFromLoadingMaxWorkers;
formsToLoadCountAtLeast = formsToLoad.Take(take).Count();
if (formsToLoadCountAtLeast < take)
formsToLoadCount = formsToLoadCountAtLeast;
}
// Determine number of jobs
if (formsToLoadCount > 0)
{
// Use known number of forms to load
jobs = Math.Min(formsToLoadCount / context.AsyncFormLoadingWorkerThreshold + 1, context.AsyncFromLoadingMaxWorkers);
}
else
{
// Use minimal determined number of forms to load
jobs = Math.Min(formsToLoadCountAtLeast / context.AsyncFormLoadingWorkerThreshold + 1, context.AsyncFromLoadingMaxWorkers);
}
}
// Indicate that total number of forms to load will be determined during iteration
bool formsToLoadIsUnknown = formsToLoadCount == 0;
if (formsToLoadIsUnknown)
{
Log.Fine("Total number of forms to load is not unknown");
if (context.AsyncFormLoading)
{
Log.Fine("Using {0} background jobs to load more than {1} forms", jobs, formsToLoadCountAtLeast);
}
}
else if (context.AsyncFormLoading)
{
Log.Fine("Using {0} background jobs to load {1} forms", jobs, formsToLoadCount);
}
using (var loader = new FormLoader(this, reader, lazyLoading, jobs))
{
using (var progress = Display.StartProgress("Loading forms"))
{
foreach (Form form in formsToLoad)
{
// Do not load froms which have been injected during indexing
if (!form.IsInjected && !form.IsHardcoded)
{
loader.LoadForm(form);
}
// Unknown total number of forms to load
// has to be determined during iteration
if (formsToLoadIsUnknown)
formsToLoadCount++;
var lastFormLoaded = loader.LastFormLoaded;
progress.Update(loader.Loaded, Math.Max(formsToLoadCount, formsToLoadCountAtLeast),
"{0} {1}", fileName, lastFormLoaded == null ? string.Empty : lastFormLoaded.ToString());
}
if (context.AsyncFormLoading)
{
// Tell loader no more forms will be loaded
loader.Complete();
// Show progress while loader is still busy
while (loader.IsBusy)
{
System.Threading.Thread.Sleep(30);
var lastFormLoaded = loader.LastFormLoaded;
progress.Update(loader.Loaded, Math.Max(formsToLoadCount, formsToLoadCountAtLeast),
"{0} {1}", fileName, lastFormLoaded == null ? string.Empty : lastFormLoaded.ToString());
}
// Wait for loader to finish completely
Log.Fine("Waiting for background jobs to finish");
loader.WaitForCompleted();
}
}
Log.Info("Loaded {0} forms from {1} ({2} supported, {3} unsupported)", loader.Loaded, fileName, loader.Supported, loader.Unsupported);
if (loader.Skipped > 0)
Log.Info("Skipped {0} forms that had been already loaded", loader.Skipped);
}
}
}
}