我是团结的新手,我不知道如何统一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);
}
}
});
}
答案 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);
}