Loading BitmapImages out of a Zip file
var zipFile = ZipFile.OpenRead(ChapterLocation);
    ...
    zipFile.Dispose();



One word: using.




    using (var stream = z.Open())
    {
        using (var mstream = new MemoryStream())
        {
            stream.CopyTo(mstream);
            mstream.Position = 0;

            var bitmap = new BitmapImage();
            bitmap.BeginInit();
            bitmap.CacheOption = BitmapCacheOption.OnLoad;
            bitmap.StreamSource = mstream;

            bitmap.EndInit();
            bitmap.Freeze();



This needs a comment explaining why mstream is necessary and you can't just use stream.

I suspect that really mstream is either unnecessary or insufficient. If it's necessary then it's probably because of threading issues due to multiple ZipArchiveEntry streams all reading from one backing stream, and in that case doing the read with stream.CopyTo might be reducing the probability of the problem surfacing rather than actually fixing it.




    foreach (ZipArchiveEntry z in zipFile.Entries)
    {
        Thread t = new Thread(() =&gt; BitmapLoad(z));
        t.Start();
        t.Join();
        Debug.WriteLine(z.Name);
    }



Ah, it's not really multi-threaded after all. If you want to do old-school multithreading then you need to spin off all of the threads before calling Join().

I say "old-school" because a more modern approach would be to use Parallel Linq. Bearing in mind my previous comment about streams, the approach would probably be to map the entries to (string Name, MemoryStream ms)s in one thread and then map those tuples to Pages in parallel threads. I think that this can be written as

Pages = zipFile.Entries.
    Select(z =&gt; Read(z)).
    AsParallel().
    Select(tuple =&gt; LoadPage(tuple)).
    OrderBy(page =&gt; page).
    ToList();


but I haven't really used Parallel Linq myself, and I don't guarantee that this does the Read calls all in the same thread.