Parse.com - 如何统一回调功能?

时间:2015-08-01 05:41:23

标签: c# multithreading parse-platform unity3d callback

我是团结的新手,我不知道如何统一callBack function。 现在我正在做的是我进行查询以从parse.com获取数据。数据正确,但在我设置禁用/启用任何gameobject的同一功能,然后我得到主线程的错误。确切的错误消息是: -

错误 -

  

只能从主线程调用SetActive。   加载场景时,将从加载线程执行构造函数和字段初始值设定项。   不要在构造函数或字段初始值设定项中使用此函数,而是将初始化代码移动到唤醒或启动函数。

我用以获取数据的以下代码/函数。

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);
                }
            }
        });

    }

2 个答案:

答案 0 :(得分:1)

您不能从另一个线程调用单位函数。因此,如果您希望您的函数在主线程上运行,请执行以下步骤:

1.在场景中创建一个游戏对象并添加一个脚本:

公共课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.ExecuteOnMainThread.Enqueue(()=&gt; {StartCoroutine(WaitAlertView4());});

它将在主线程可以执行的下一个机会,或者更确切地说,当游戏对象将调用它的更新方法时

答案 1 :(得分:0)

您无法从后台线程更新UI。似乎scoreapp42.instance.loadingwindow指向一个UI对象,这就是为什么你看到上面描述的错误。

事实证明,System.Windows.Threading命名空间属于用于Windows Presentation Framework的WindowsBase程序集。因此,使用Dispatcher的想法不适用于此方案。解锁自己的唯一方法是不在后台线程中进行任何UI工作。而是等到后台线程成功完成,然后进行UI工作。

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);
}