2015-08-01 1 views
2

Я новичок в единстве, и я не знаю, как сделать callBack function в единстве. Теперь я делаю запрос, чтобы получить данные от parse.com. Данные поступают правильно, но в той же функции, когда я устанавливаю disable/enable any gameobject, я получаю ошибку основного потока. Точное сообщение об ошибке: -Parse.com - Как сделать функцию обратного вызова в единстве?

error-

SetActive можно назвать только из основного потока. Конструкторы и инициализаторы полей будут выполняться из загрузочной нити при загрузке сцены. Не используйте эту функцию в инициализаторах конструктора или поля, вместо этого переместите код инициализации в функцию Awake или Start.

следующий код/​​функция, которую я использую для получения данных.

public void GetTop10ScoreClassic() 
    { 
     List<string> fbscores=new List<string>(); 
     List<string> fbplayer=new List<string>(); 
     int i = 0; 
     int rank = 0; 
//  Debug.Log (PlayerPrefs.GetString ("FBUserId")); 
     Debug.Log ("Classic top 10 1"); 
     var query = ParseObject.GetQuery ("ClassicFacebookScore").OrderByDescending("score").Limit(10).WhereContainedIn("userId",FBLogin.friendIDsFromFB); 

     query.FindAsync().ContinueWith(t => 
             { 
      Debug.Log ("Classic top 10 2"); 


      comments = t.Result; 
      Debug.Log(t.Result); 

      foreach (var obj in comments) { 
       i++; 
       int score = obj.Get<int>("score"); 
       Debug.Log(score); 
       string playerName = obj.Get<string>("playerName"); 
       Debug.Log(playerName); 
       string playerId=obj.Get<string>("userId"); 
       Debug.Log(playerId); 

       fbscores.Add(score.ToString()); 
       fbplayer.Add(playerName); 

       if(playerId==userId) 
       { 
        rank=i;// to highlight the user's score 
       } 
      } 

      //enable the colliders 
      foreach (BoxCollider2D colliders in Userrankscore.instance.myColliders) 
       colliders.enabled = true; 

      FbLeaderboard.instance.NetworkError = false; 
      scoreapp42.instance.loadingwindow.SetActive (false); 

       //Pass the list of score; 
      App42Score.instance.list (fbscores,fbplayer,"fb",Convert.ToInt32(rank)); 


      if(t.IsFaulted) 
      { 
       //enable the colliders 
       foreach (BoxCollider2D colliders in Userrankscore.instance.myColliders) 
        colliders.enabled = true; 
       if(FbLeaderboard.instance.NetworkError) 
       { 
        scoreapp42.instance.errorwindow.SetActive(true); 
        scoreapp42.instance.loadingwindow.SetActive (false); 
        Debug.LogError("Network Error"); 
       } 

       foreach(var e in t.Exception.InnerExceptions) { 
        ParseException parseException = (ParseException) e; 
        Debug.Log("Error message " + parseException.Message); 
        Debug.Log("Error code: " + parseException.Code); 
       } 
      } 
     }); 

    } 

ответ

0

Вы не можете обновить пользовательский интерфейс из фоновой темы. Похоже, что scoreapp42.instance.loadingwindow указывает на объект пользовательского интерфейса, поэтому вы видите ошибку, описанную выше.

Оказывается, пространство имен System.Windows.Threading принадлежит к сборке WindowsBase, которая используется для Windows Presentation Framework. Таким образом, идея использования диспетчера не применима в этом сценарии. Единственный способ разблокировать себя - не выполнять какой-либо пользовательский интерфейс в фоновом потоке. Вместо этого подождите, пока фоновый поток завершится успешно, а затем выполните работу пользовательского интерфейса.

var query = ...; 
var backgroundWork = query.FindAsync().ContinueWith(t => 
{ 
    ... 

    //enable the colliders 
    foreach (BoxCollider2D colliders in Userrankscore.instance.myColliders) 
     colliders.enabled = true; 

    FbLeaderboard.instance.NetworkError = false; 
    //scoreapp42.instance.loadingwindow.SetActive(false); 

    //Pass the list of score; 
    App42Score.instance.list (fbscores,fbplayer,"fb",Convert.ToInt32(rank)); 

    ... 
}); 

// wait till the background work has completed 
backgroundWork.Wait(); 

if (backgroundWork.IsCompleted) 
{ 
    // now do any UI related work 
    scoreapp42.instance.loadingwindow.SetActive(false); 
} 
+0

как я могу назвать это из основного потока, или как я могу перейти к главной теме. пожалуйста, дайте некоторое объяснение с помощью кода. –

+0

Можете ли вы попробовать включить фрагмент кода, который я указал здесь? Диспетчер в основном запускает код в основном потоке. В текущем состоянии ваш код запускает все из фонового потока. –

+0

как можно добавить это при добавлении Dispatcher.Invoke (() => {scoreapp42.instance.loadingwindow.seActive (false);} эта строка вместо scoreapp42.instance.loadingwindow.seActive (false); тогда у меня появилось много ошибка. Пожалуйста, помогите мне –

1

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

1.Create геймобжекты в вашей сцене и добавить этот скрипт:

общественного класса DoOnMainThread: MonoBehaviour {

public readonly static Queue<Action> ExecuteOnMainThread = new Queue<Action>(); 

public virtual void Update() 
{ 
    // dispatch stuff on main thread 
    while (ExecuteOnMainThread.Count > 0) 
    { 
     ExecuteOnMainThread.Dequeue().Invoke(); 
    } 
} 

}

2) Добавить действие сопрограммы в очередь, когда вы хотите назвать это так:

DoOnMainThread.ExecuteOn MainThread.Enqueue (() => {StartCoroutine (WaitAlertView4()); });

будет выполнена следующая возможность основной поток может, или, вернее, когда объект игры будет вызывать это метод обновления