2017-11-18 11 views
0

게임의 데이터 텍스트를로드하고 구문 분석 할 코드를 작성하고 있습니다. 분기 리더 호출이 많이 있습니다. 예를 들어지도에 소품이나 적과 같은 데이터가 포함되어 있고 해당 오브젝트에는 호출되어 읽히는 파일이 있습니다. 일반적으로이 모든 데이터는 빠르게로드됩니다. 약 1.5 초 느린 컴퓨터에서는 약 초 이상 걸릴 수 있고 게임 창이 끝날 때까지 응답하지 않게 할 수 있습니다.비동기 데이터 읽기/구문 분석 성능

지금 당장은로드 시간을 줄이면서 창을 활성 상태로 유지하는 방법을 모색 중입니다. 로드 중 일부를 메인 스레드의 백그라운드에서 실행되는 태스크로 분리 한 다음로드가 완료되면 메인 스레드에게 상태를 전환하도록 알려주고 게임이 계속됩니다. 이것은 작동하지만, 나는 1.5 두 번째 로딩 시간부터 두 번째로로 이동했습니다. 이런 백그라운드 작업으로 전환 할 때 정상적인 성능입니까? 현재 처리되는 방법의 예로서 일반화 된 코드를 게시했습니다.

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; 
} 
+0

나에게 보인다. 스트림 리더의 사용법을'using' 블록으로 묶는 것도 고려해보십시오. 성능에 영향을 줄 수있는 사항이 있는지 계속 읽습니다. – Fabulous

+0

@Fabulous ReadLine은 I/O 작업이므로 스레드를 차단하지 않으며 ReadLineAsync는 비동기 적으로 수행 할 필요가 없기 때문에 ReadLineAsync가 성능을 더욱 저하시킬 수 있으므로 ReadLineAsync를 사용하면 불필요한 작업이 추가됩니다 간접비. 그게 사실인가요? – DangerMcD

+0

되돌아 오는 데이터를 처리 할 때 그 차이가 미미할 수 있습니다. [이 스레드] 고려 (https://social.msdn.microsoft.com/Forums/vstudio/en-US/a47412ed-1b21-45c2-8554-cc602d6b5ddb/is-streamreaderreadlineasync-much-slower-than-readline?forum= 평행 안정성). 그곳에는 다른 측면이 있지만 귀하의 질문은 다루어집니다. 일반적으로'async/await'는 호출 스택의 모든 단계를 캐스케이드 호출합니다. 이 경우, 당신은'parseLine' 연산에서 코드를 보길 원할 것입니다. – Fabulous

답변

0

댓글로 게시 하겠지만 아직 허용되지 않으므로 완전한 설명으로 확장하십시오.

게임 개발의 관점에서, 나는 backgroundworker 스레드로 로더를 만들 것입니다. 이렇게하면 사용자 입력에 응답하는 창의 주 스레드/양식이 그대로 유지됩니다.

backgroundWorker에서 필요한 개별 작업을 수행하기 위해 개별 작업을 실행할 수 있지만 UI는 항상 응답합니다.

기억해야 할 중요한 점은 클래스의 루트에 필요한 변수를 만든 다음이를 백그라운드 스레드에 채우는 것입니다. 이렇게하면 모든 것이 메인 스레드에서 완료되면 결과를 쉽게 읽을 수 있습니다. 예를 들어

: 당신은`LoadFile` 방법에`StreamReader`에서`async` 방법을 사용할 수 있었던 것처럼

class MainThread 
{ 
    BackgroundLoader bgLoader; 

    public MainThread() 
    { 
     bgLoader = new BackgroundLoader(); 
    } 

    public void LoadItems() 
    { 
     bgLoader.Load(); 
    } 
} 

class BackgroundLoader 
{ 
    BackgroundWorker backgroundWorker = new BackgroundWorker(); 
    // create the variables to hold the results. 
    Map map; 

    public void Load() 
    { 
     backgroundWorker.WorkerReportsProgress = true; 
     backgroundWorker.WorkerSupportsCancellation = true; 
     backgroundWorker.ProgressChanged += BackgroundWorker_ProgressChanged; 
     backgroundWorker.RunWorkerCompleted += BackgroundWorker_RunWorkerCompleted; 
     backgroundWorker.DoWork += BackgroundWorker_DoWork; 
     backgroundWorker.RunWorkerAsync(); 
     while (!backgroundWorker.IsBusy) { } 
    } 

    private void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e) 
    { 
     // This is where you do the work and load your variables, which you then access once the thread is complete. 
     map = LoadMap(); 
    } 
} 
+0

감사합니다. 나는 이것이 내 문제를 해결할지는 모르지만, 조사할만한 가치가있다. – DangerMcD

+0

주 스레드에서 작업을 실행할 때 작업 속도가 느려지므로 전체 스레드를 단일 스레드로 실행 해 볼 수는 있지만 백그라운드 스레드에서만 수행 할 수 있습니다. 이로 인해보고있는 문제가 제거 될 수 있습니다. – SoulRider

+0

나는 본다! 해명 주셔서 감사합니다 :) – DangerMcD