等待在Unity3D中完成parse.com异步任务

时间:2016-01-10 15:03:34

标签: c# asynchronous parse-platform unity3d

作为我学校项目的一部分,我试图链接两个表来减少存储在一个表中的数据量,所以我想链接我的"分数"我的" CorrectAnswers"通过ObjectID类。但是,由于任务是异步的,因此当一个任务完成保存时,另一个任务已经开始或者也已完成保存,因此ObjectID返回为null。

以下是我使用的代码:

public void SaveScore()
{

    ParseObject SendScore = new ParseObject("Scores");
    SendScore["Score"] = CheckAnswer.score;
    SendScore["user"] = ParseObject.CreateWithoutData("_User", ParseUser.CurrentUser.ObjectId);
    SendScore["TestMode"] = MainMenu.testmode;
    SendScore["TotalQuestions"] = QuestionCreation.TotalQuestions;
    SendScore["CorrectQuestions"] = CheckAnswer.CorrectQuestions;


    SendScore.SaveAsync().ContinueWith(t =>
    {
        ScoreObjectId = SendScore.ObjectId;
    });

    ParseObject SendCorrectTopics = new ParseObject("CorrectAnswers");
    SendCorrectTopics["Score"] = SendScore.ObjectId;
    for (int i = 0; i <= 9; i++)
    {
        string Topic = "Topic" + (i + 1).ToString();
        SendCorrectTopics[Topic] = CheckAnswer.CorrectTopics[i];
    }

    SendCorrectTopics.SaveAsync();

    SceneManager.LoadScene(0);
}

在第一次保存完成之前,我怎么能保持第二次保存?我对C#有点新鲜,所以还不太了解它的全部功能。我已经调查了等待&#34;等待&#34;但团结似乎并不喜欢这样。任何帮助将不胜感激! 提前谢谢,

3 个答案:

答案 0 :(得分:1)

编辑:好的,在对Unity的协同程序进行了一些阅读之后,我发现了一种更好的检查方法,它只依赖于在需要时进行检查:

 IEnumerator CheckSave()
{
    while(ScoreObjectId == null & !DoneSave))
    {
        print("Running");
        yield return new WaitForSeconds(0.5f);
    }
    DoneSave = false;
    SaveTotalTopics();

}

这似乎是一种更好的方法。

好吧,似乎答案是我之前已经做过的事情,即使它有点难看。

使用Unity的更新功能我创建了一个检查,以确保ObjectID不为null并且之前的保存已完成,如下所示:

void Update () {
    if (ScoreObjectId != null & DoneSave)
    {
        DoneSave = false;
        SaveTotalTopics();
    }

因此将其拆分为两个保存并创建:

    public void SaveScore()
{
    ParseObject SendScore = new ParseObject("Scores");
    SendScore["Score"] = CheckAnswer.score;
    SendScore["user"] = ParseObject.CreateWithoutData("_User", ParseUser.CurrentUser.ObjectId);
    SendScore["TestMode"] = MainMenu.testmode;
    SendScore["TotalQuestions"] = QuestionCreation.TotalQuestions;
    SendScore["CorrectQuestions"] = CheckAnswer.CorrectQuestions;

    Task SendingScores = SendScore.SaveAsync().ContinueWith(t =>
    {
        if (t.IsFaulted || t.IsCanceled)
        {
            DoneSave = false;
            print(t.Exception);
        }
        else
        {
            DoneSave = true;
            print("Setting object ID!");
            ScoreObjectId = SendScore.ObjectId;
            print(ScoreObjectId); 
        }
    });

}



void SaveTotalTopics()
{
    for (int i = 0; i <= 9; i++)
    {
        string Topic = "Topic" + (i + 1).ToString();
        SendCorrectTopics[Topic] = CheckAnswer.CorrectTopics[i];
    }

    SendCorrectTopics["UserScore"] = ParseObject.CreateWithoutData("Scores", ScoreObjectId);
    SendCorrectTopics.SaveAsync().ContinueWith(t =>
    {
        if(t.IsFaulted || t.IsCanceled)
        {
            print(t.Exception);
        }
        else
        {
            print("Saved!");
        }
    });
}

我也忘了使用ParseObject.CreateWithoutData(),所以即使我找到了更好的方法,我的第一个代码片段也不会有用......

所以,虽然我对最终结果不满意,但至少它是有效的,我不认为每一帧运行if语句都会对我的游戏性能产生重大影响。

答案 1 :(得分:0)

SendScore.SaveAsync().ContinueWith(t =>
{
    ScoreObjectId = SendScore.ObjectId;
});

这是您在任务完成后放置要执行的操作的位置。尝试在ScoreObjectId行下面添加debug来测试它。

答案 2 :(得分:0)

为什么不使用bool和while循环?

public IEnumerator SaveScore()
{

    bool canContinue = false;
    ParseObject SendScore = new ParseObject("Scores");
    SendScore["Score"] = CheckAnswer.score;
    SendScore["user"] = ParseObject.CreateWithoutData("_User", ParseUser.CurrentUser.ObjectId);
    SendScore["TestMode"] = MainMenu.testmode;
    SendScore["TotalQuestions"] = QuestionCreation.TotalQuestions;
    SendScore["CorrectQuestions"] = CheckAnswer.CorrectQuestions;


    SendScore.SaveAsync().ContinueWith(t =>
    {
        ScoreObjectId = SendScore.ObjectId;
        //set the bool canContinue to true because the first portion of code has finished running
        canContinue = true;
    });

    //wait while the canContinue bool is false
    while(!canContinue){
        yield return null;
    }

    //continue your parse code
    ParseObject SendCorrectTopics = new ParseObject("CorrectAnswers");
    SendCorrectTopics["Score"] = SendScore.ObjectId;
    for (int i = 0; i <= 9; i++)
    {
        string Topic = "Topic" + (i + 1).ToString();
        SendCorrectTopics[Topic] = CheckAnswer.CorrectTopics[i];
    }

    SendCorrectTopics.SaveAsync();

    SceneManager.LoadScene(0);
    return null;
}