Ich schreibe Code zum Laden und Parsen von Text für Daten in einem Spiel. Es gibt viele verzweigende Leser-Aufrufe - zum Beispiel, eine Karte wird Daten wie Requisiten und Feinde enthalten, und diese Objekte haben ihre eigenen Dateien, die aufgerufen und eingelesen werden. Dies wird normalerweise schnell geladen, etwa 1,5 Sekunden, aber auf langsameren Maschinen kann es dauern, 5+ Sekunden und das Spielfenster zu reagieren, bis es fertig ist.Async Data Reading/Parsing Leistung
Im Moment suche ich nach Möglichkeiten, das Fenster aktiv zu halten, während die Ladezeiten immer noch kurz sind. Ich habe einige der Ladevorgänge in Tasks getrennt, die im Hintergrund des Hauptthreads ausgeführt werden, und wenn das Laden beendet ist, teilt es dem Hauptthread mit, die Zustände zu wechseln, und das Spiel wird fortgesetzt. Dies funktioniert jedoch, nachdem ich eine zweite Ladezeit von einer zweiten Ladezeit auf eine zweite Ladezeit übergegangen bin. Ist das eine normale Leistung beim Wechsel zu einer Hintergrundaufgabe? Ich habe einen verallgemeinerten Code als Beispiel dafür angegeben, wie er derzeit gehandhabt wird.
Map map = null;
//Main Update Loop
public void Update()
{
if(GameState == Active)
map.Update();
else
ShowLoadingScreen();
}
//LoadWorld gets called from elsewhere, like a UI
public async void LoadWorld()
{
GameState = State.Loading;
await Task.Run(() => { LoadFile("mapdata", out map); });
GameState = State.Active;
map.Start();
}
//This loads the file and reads the first line
//which tells the reader what sort of object it is
public void LoadFile(String file, out Map m)
{
m = new Map(); //create new map
StreamReader sr = new StreamReader(file);
String line;
Object obj = null;
while ((line = sr.ReadLine()) != null)
{
switch(line)
{
case "A":
obj = parseObjectA(line, sr); //continues with its own loop
break;
case "B":
obj = parseObjectB(line, sr); //continues with its own loop
break;
}
map.addObject(obj);
}
}
//This loops through the reader and fills an object with data, then returns it
public Object parseObjectA(String line, StreamReader sr)
{
Object obj = new Object();
while ((line = sr.ReadLine()) != null)
{
String element;
String value;
//parseLine is a function that breaks apart the line into an element and value
parseLine(line, out element, out value);
switch(element)
{
case "name":
obj.Name = value;
break;
case "position":
{
int pos = 0;
Int32.TryParse(value, out pos);
obj.position = pos;
break;
}
}
}
return obj;
}
mir Sieht aus wie Sie die 'async' Methoden von Ihrem' StreamReader' im 'LoadFile' Methode verwenden könnte. Erwägen Sie auch, die Verwendung Ihres Stream-Readers in einem 'using'-Block zu verpacken. Ich lese weiter, um zu sehen, ob es noch etwas gibt, das die Leistung beeinträchtigen könnte. – Fabulous
@Fabulous Von dem, was mir zuvor gesagt wurde, blockiert ReadLine keine Threads, da es sich um eine E/A-Operation handelt und ReadLineAsync könnte die Leistung sogar noch weiter verringern, da das Lesen nicht asynchron erfolgen muss Overhead. Ist das wahr? – DangerMcD
Wenn Sie eine signifikante Verarbeitung der Daten durchführen, die Sie zurück erhalten, kann der Unterschied vernachlässigbar sein. Betrachten Sie [diesen Thread] (https://social.msdn.microsoft.com/Forums/vstudio/en-US/a47412ed-1b21-45c2-8554-cc602d6b5ddb/is-streamreaderreadlineasync-much-slower-than-readline?forum= Parallelextension), wenn dieses Problem angesprochen wird. Es gibt andere Aspekte der Frage, aber Ihre Frage wird angesprochen. Gewöhnlich "async/await" -Aufrufe kaskadieren den gesamten Call-Stack hinunter. In diesem Fall sollten Sie sich den Code in Ihrer 'parseLine'-Operation ansehen. – Fabulous