2015-06-29 3 views
0

Я делаю кусок кода, который получает часть информации из MySQL и отображает ее в пользовательском интерфейсе. проблема в том, что программа не дождалась завершения запроса MySQL и переходит прямо к отображению переменной (которая пуста, потому что результаты запроса не были выполнены вовремя)Как дождаться завершения StartCoroutine() перед продолжением

Грубая схема мой код будет:

bool notYetDone = true; 

StartCoroutine(query(web)); 

IEnumerator query (WWW web){ 
    yield return web; 
    while(notYetDone == true){ 
     yield return new WaitForSeconds(1f); 
     if(web.error == null){ 
      //no problems with the query, some code here 
      notYetDone = false; 
     } else if (web.error != null){ 
      //some code here for handling errors 
     } else { 
      Debug.Log("i dont really know why we reached here"); 
     } 
    } 
} 

что-то я заметил, что это, кажется, изменить значение notYetDone и немедленно заканчивает цикл. Что-то не так в моем коде? Заранее спасибо.

+0

попробуйте использовать web.isDone вместо notYetDone == true –

+0

, непосредственно заменяя аргумент while аргументом web.isDone, создает бесконечный цикл. но плохо попробуйте некоторые способы использования этого. спасибо за предложение – ryuuuuuusei

+0

Что делать, если вы используете: while (! web.isDone), поэтому, когда он закончит, это будет верно и выйдет из цикла. –

ответ

2

попробовать:

IEnumerator query (WWW web) 
{ 
    //yield return web; 
    while(!web.isDone && web.Error == null) 
    { 
    //this will loop until your query is finished 
    //do something while waiting... 
     yield return null; 
    } 
    if(web.Error != null) 
    Debug.Log("Errors on web"); 

} 
+0

Это неверно по двум причинам: yield return web; достаточно, чтобы дождаться конца процедуры www, поэтому цикл while бесполезен, но если кодер забывает уступать в сети до этого, он будет блокировать поток до завершения. чтобы убедиться, что вы должны либо полностью удалить его, либо получить нуль внутри –

+0

ну ... вы правы, вам не нужно в то время, или вы можете удалить веб-сайт возврата дохода и сделать что-то вроде while (! web.isDone && web. Ошибка == null) {yield return null} if (error! = Null) {Debug.Log («Ошибки в сети»)}, цикл while на всякий случай, когда он хочет что-то сделать, пока выполняется запрос ... –

+0

Теперь это правильно –

2

Попробуйте это:

class QueryBehaviour: MonoBehaviour 
{ 
    bool queryFinished = false; 
    WWW wwwQuery; 

    IEnumerator Query() 
    { 
    wwwQuery = new WWW("url_to_query"); 
    yield return wwwQuery; 

    queryFinished = true; 
    //results or error should be here 
    } 

    Update() 
    { 
    if(queryFinished == false) 
    { 
     return; 
    } 
    else 
    { 
     //use wwwQuery here 
    } 
    } 
} 

Тогда просто позвоните Query.

Примечание: нет необходимости ждать, если вы вызываете доходность возврата wwwQuery. Вы должны заняты, если вы не хотите этого делать, например, вы хотите проверить загрузку прогресса, и в этом случае вам следует опросить результат класса www внутри метода Update, определенного в MonoBehaviour.

+0

извините, но он по-прежнему переходит к следующей строке кода. – ryuuuuuusei

+0

Хорошо, теперь я понял, да, это идет к следующей строке кода. Операция асинхронна. Вам нужно установить флаг после доходности, а затем у вас должен быть запрос –

+0

вы можете объяснить поток этого? – ryuuuuuusei

0

Размещение ключевых слов, прежде чем выход startcoroutine также будет иметь тот же эффект. В вашем случае:

yield StartCoroutine(query(web)); 
//at this point it is guaranteed to be completed 

http://docs.unity3d.com/ScriptReference/MonoBehaviour.StartCoroutine.html

+0

Но для этого вам нужно уже находиться внутри сопрограммы. Возможно, вы думали о 'IEnumerator Start() {}' –

+0

yeild можно использовать только внутри Couroutine !!! –

0

Как об использовании обратных вызовов?

public void showMessage(string message) 
    { 
     setMessage(message); 
     Debug.Log("start_fadeIn"); 
     StartCoroutine(coroutine__fadeIn(delegate 
     { 
      Debug.Log("start_fadeOut"); 
      StartCoroutine(coroutine__fadeOut(delegate 
      { 
       Debug.Log("done"); 
      })); 
     })); 
    } 


    private IEnumerator coroutine__fadeIn(Action completion) 
    { 
     CanvasGroup canvasGroup = GetComponent<CanvasGroup>(); 
     for (float f = 0f; f <= 1; f += 0.01f) 
     { 
      canvasGroup.alpha = f; 
      yield return null; 
     } 

     completion(); 
    } 

    private IEnumerator coroutine__fadeOut(Action completion) 
    { 
     CanvasGroup canvasGroup = GetComponent<CanvasGroup>(); 
     for (float f = 1f; f >= 0; f -= 0.01f) 
     { 
      canvasGroup.alpha = f; 
      yield return null; 
     } 

     completion(); 
    } 

Внимание, этот способ требует использования версии .NET, которая поддерживает Действие класса.