Only update the loading screen from the main thread

Fixes the crash experienced by pchote. It's a hack but it's easy
to get rid of and it will have to do for now, until the messy
LoadScreen gets fixed.
This commit is contained in:
Pavlos Touboulidis
2014-05-13 17:56:27 +03:00
parent a845947e0f
commit ca44be7b2e
4 changed files with 22 additions and 25 deletions

View File

@@ -31,13 +31,16 @@ namespace OpenRA
readonly Dictionary<string, TileSet> tileSetCache = new Dictionary<string, TileSet>(); readonly Dictionary<string, TileSet> tileSetCache = new Dictionary<string, TileSet>();
readonly Dictionary<string, SequenceCache> sequenceCaches = new Dictionary<string, SequenceCache>(); readonly Dictionary<string, SequenceCache> sequenceCaches = new Dictionary<string, SequenceCache>();
public Action OnProgress; public event EventHandler LoadingProgress;
void RaiseProgress()
{
if (LoadingProgress != null)
LoadingProgress(this, new EventArgs());
}
public RulesetCache(ModData modData) public RulesetCache(ModData modData)
{ {
this.modData = modData; this.modData = modData;
OnProgress = () => { if (modData.LoadScreen != null) modData.LoadScreen.Display(); };
} }
public Ruleset LoadDefaultRules() public Ruleset LoadDefaultRules()
@@ -57,31 +60,23 @@ namespace OpenRA
Dictionary<string, string> movies; Dictionary<string, string> movies;
Dictionary<string, TileSet> tileSets; Dictionary<string, TileSet> tileSets;
OnProgress();
using (new PerfTimer("Actors")) using (new PerfTimer("Actors"))
actors = LoadYamlRules(actorCache, m.Rules, map.RuleDefinitions, (k, y) => new ActorInfo(k.Key.ToLowerInvariant(), k.Value, y)); actors = LoadYamlRules(actorCache, m.Rules, map.RuleDefinitions, (k, y) => new ActorInfo(k.Key.ToLowerInvariant(), k.Value, y));
OnProgress();
using (new PerfTimer("Weapons")) using (new PerfTimer("Weapons"))
weapons = LoadYamlRules(weaponCache, m.Weapons, map.WeaponDefinitions, (k, _) => new WeaponInfo(k.Key.ToLowerInvariant(), k.Value)); weapons = LoadYamlRules(weaponCache, m.Weapons, map.WeaponDefinitions, (k, _) => new WeaponInfo(k.Key.ToLowerInvariant(), k.Value));
OnProgress();
using (new PerfTimer("Voices")) using (new PerfTimer("Voices"))
voices = LoadYamlRules(voiceCache, m.Voices, map.VoiceDefinitions, (k, _) => new SoundInfo(k.Value)); voices = LoadYamlRules(voiceCache, m.Voices, map.VoiceDefinitions, (k, _) => new SoundInfo(k.Value));
OnProgress();
using (new PerfTimer("Notifications")) using (new PerfTimer("Notifications"))
notifications = LoadYamlRules(notificationCache, m.Notifications, map.NotificationDefinitions, (k, _) => new SoundInfo(k.Value)); notifications = LoadYamlRules(notificationCache, m.Notifications, map.NotificationDefinitions, (k, _) => new SoundInfo(k.Value));
OnProgress();
using (new PerfTimer("Music")) using (new PerfTimer("Music"))
music = LoadYamlRules(musicCache, m.Music, new List<MiniYamlNode>(), (k, _) => new MusicInfo(k.Key, k.Value)); music = LoadYamlRules(musicCache, m.Music, new List<MiniYamlNode>(), (k, _) => new MusicInfo(k.Key, k.Value));
OnProgress();
using (new PerfTimer("Movies")) using (new PerfTimer("Movies"))
movies = LoadYamlRules(movieCache, m.Movies, new List<MiniYamlNode>(), (k, v) => k.Value.Value); movies = LoadYamlRules(movieCache, m.Movies, new List<MiniYamlNode>(), (k, v) => k.Value.Value);
OnProgress();
using (new PerfTimer("TileSets")) using (new PerfTimer("TileSets"))
tileSets = LoadTileSets(tileSetCache, sequenceCaches, m.TileSets); tileSets = LoadTileSets(tileSetCache, sequenceCaches, m.TileSets);
var sequences = sequenceCaches.ToDictionary(kvp => kvp.Key, kvp => new SequenceProvider(kvp.Value, map)); var sequences = sequenceCaches.ToDictionary(kvp => kvp.Key, kvp => new SequenceProvider(kvp.Value, map));
OnProgress();
return new Ruleset(actors, weapons, voices, notifications, music, movies, tileSets, sequences); return new Ruleset(actors, weapons, voices, notifications, music, movies, tileSets, sequences);
} }
@@ -90,6 +85,8 @@ namespace OpenRA
string[] files, List<MiniYamlNode> nodes, string[] files, List<MiniYamlNode> nodes,
Func<MiniYamlNode, Dictionary<string, MiniYaml>, T> f) Func<MiniYamlNode, Dictionary<string, MiniYaml>, T> f)
{ {
RaiseProgress();
var inputKey = string.Concat(string.Join("|", files), "|", nodes.WriteToString()); var inputKey = string.Concat(string.Join("|", files), "|", nodes.WriteToString());
var mergedNodes = files var mergedNodes = files
@@ -105,12 +102,15 @@ namespace OpenRA
t = f(wkv, wyy); t = f(wkv, wyy);
itemCache.Add(key, t); itemCache.Add(key, t);
RaiseProgress();
return t; return t;
}; };
var yy = mergedNodes.ToDictionary(x => x.Key, x => x.Value); var yy = mergedNodes.ToDictionary(x => x.Key, x => x.Value);
var itemSet = mergedNodes.ToDictionaryWithConflictLog(kv => kv.Key.ToLowerInvariant(), kv => wrap(kv, yy), "LoadYamlRules", null, null); var itemSet = mergedNodes.ToDictionaryWithConflictLog(kv => kv.Key.ToLowerInvariant(), kv => wrap(kv, yy), "LoadYamlRules", null, null);
RaiseProgress();
return itemSet; return itemSet;
} }

View File

@@ -22,12 +22,8 @@ namespace OpenRA.Graphics
Dictionary<string, CursorSequence> cursors; Dictionary<string, CursorSequence> cursors;
Cache<string, PaletteReference> palettes; Cache<string, PaletteReference> palettes;
public Action OnProgress;
public CursorProvider(ModData modData) public CursorProvider(ModData modData)
{ {
OnProgress = () => { if (modData.LoadScreen != null) modData.LoadScreen.Display(); };
var sequenceFiles = modData.Manifest.Cursors; var sequenceFiles = modData.Manifest.Cursors;
cursors = new Dictionary<string, CursorSequence>(); cursors = new Dictionary<string, CursorSequence>();
@@ -65,8 +61,6 @@ namespace OpenRA.Graphics
void LoadSequencesForCursor(SpriteLoader loader, string cursorSrc, MiniYaml cursor) void LoadSequencesForCursor(SpriteLoader loader, string cursorSrc, MiniYaml cursor)
{ {
OnProgress();
foreach (var sequence in cursor.Nodes) foreach (var sequence in cursor.Nodes)
cursors.Add(sequence.Key, new CursorSequence(loader, cursorSrc, cursor.Value, sequence.Value)); cursors.Add(sequence.Key, new CursorSequence(loader, cursorSrc, cursor.Value, sequence.Value));
} }

View File

@@ -68,12 +68,8 @@ namespace OpenRA.Graphics
readonly Dictionary<string, Lazy<IReadOnlyDictionary<string, Sequence>>> sequenceCache = new Dictionary<string, Lazy<IReadOnlyDictionary<string, Sequence>>>(); readonly Dictionary<string, Lazy<IReadOnlyDictionary<string, Sequence>>> sequenceCache = new Dictionary<string, Lazy<IReadOnlyDictionary<string, Sequence>>>();
public Action OnProgress;
public SequenceCache(ModData modData, TileSet tileSet) public SequenceCache(ModData modData, TileSet tileSet)
{ {
OnProgress = () => { if (modData.LoadScreen != null) modData.LoadScreen.Display(); };
this.modData = modData; this.modData = modData;
spriteLoader = Exts.Lazy(() => new SpriteLoader(tileSet.Extensions, new SheetBuilder(SheetType.Indexed))); spriteLoader = Exts.Lazy(() => new SpriteLoader(tileSet.Extensions, new SheetBuilder(SheetType.Indexed)));
@@ -87,8 +83,6 @@ namespace OpenRA.Graphics
IReadOnlyDictionary<string, Lazy<IReadOnlyDictionary<string, Sequence>>> Load(List<MiniYamlNode> sequenceNodes) IReadOnlyDictionary<string, Lazy<IReadOnlyDictionary<string, Sequence>>> Load(List<MiniYamlNode> sequenceNodes)
{ {
OnProgress();
var sequenceFiles = modData.Manifest.Sequences; var sequenceFiles = modData.Manifest.Sequences;
var nodes = sequenceFiles var nodes = sequenceFiles
@@ -113,8 +107,6 @@ namespace OpenRA.Graphics
sequenceCache.Add(key, t); sequenceCache.Add(key, t);
items.Add(node.Key, t); items.Add(node.Key, t);
} }
OnProgress();
} }
return new ReadOnlyDictionary<string, Lazy<IReadOnlyDictionary<string, Sequence>>>(items); return new ReadOnlyDictionary<string, Lazy<IReadOnlyDictionary<string, Sequence>>>(items);

View File

@@ -42,6 +42,7 @@ namespace OpenRA
LoadScreen.Display(); LoadScreen.Display();
WidgetLoader = new WidgetLoader(this); WidgetLoader = new WidgetLoader(this);
RulesetCache = new RulesetCache(this); RulesetCache = new RulesetCache(this);
RulesetCache.LoadingProgress += HandleLoadingProgress;
MapCache = new MapCache(this); MapCache = new MapCache(this);
// HACK: Mount only local folders so we have a half-working environment for the asset installer // HACK: Mount only local folders so we have a half-working environment for the asset installer
@@ -50,6 +51,16 @@ namespace OpenRA
GlobalFileSystem.Mount(dir); GlobalFileSystem.Mount(dir);
defaultRules = Exts.Lazy(() => RulesetCache.LoadDefaultRules()); defaultRules = Exts.Lazy(() => RulesetCache.LoadDefaultRules());
initialThreadId = System.Threading.Thread.CurrentThread.ManagedThreadId;
}
// HACK: Only update the loading screen if we're in the main thread.
int initialThreadId;
void HandleLoadingProgress(object sender, EventArgs e)
{
if (LoadScreen != null && System.Threading.Thread.CurrentThread.ManagedThreadId == initialThreadId)
LoadScreen.Display();
} }
public void InitializeLoaders() public void InitializeLoaders()