emreoktem
emreoktem

Reputation: 2547

Main thread issue with Parse.com queries

I am trying to use parse.com service with my unity game. My problem is instantiating objects according to the results received from a query.

For example, when I run the below code;

var queryCurrent = ParseObject.GetQuery("Levels")
.WhereEqualTo("ItemId", "Character")
.WhereEqualTo("Level", "3");

queryCurrent.FirstAsync().ContinueWith(t =>
{
    Character character = ScriptableObject.CreateInstance<Character>();
});

I receive the following error;

CreateInstanceFromType can only be called from the main thread. Constructors and field initializers will be executed from the loading thread when loading a scene. Don't use this function in the constructor or field initializers, instead move initialization code to the Awake or Start function.

It seems that this is a general problem and everyone tries to find a workaround by using coroutines. An optimized solution will be appreciated.

Thanks in advance.

Upvotes: 2

Views: 1546

Answers (1)

Fosco
Fosco

Reputation: 38526

Use a Coroutine to run things on the main thread. It's documented on the Parse site here: https://parse.com/docs/unity_guide#tasks-coroutines

edit:

Unity provides the notion of a Coroutine for cooperative multitasking, allowing code to be interleaved while all running on the main thread. Tasks and the continuation model are mostly independent of this multitasking mechanism, but are easy to adapt to work within a coroutine. Your coroutine can simply check the IsCompleted property of a task to know whether the asynchronous work has completed, allowing the coroutine to continue where it left off. For example, the following coroutine code saves an object and then waits for a query to return:

public IEnumerator GameOver()
{
    var gameHistory = new ParseObject("GameHistory");
    gameHistory["score"] = score;
    gameHistory["player"] = ParseUser.CurrentUser;

    var saveTask = gameHistory.SaveAsync();
    while (!saveTask.IsCompleted) yield return null;

    // When the coroutine reaches this point, the save will be complete

    var historyQuery = new ParseQuery<ParseObject>("GameHistory")
        .WhereEqualTo("player", ParseUser.CurrentUser)
        .OrderByDescending("createdAt");

    var queryTask = historyQuery.FindAsync();
    while (!queryTask.IsCompleted) yield return null;

    // The task is complete, so we can simply check for its result to get
    // the current player's game history
    var history = queryTask.Result;
}

Upvotes: 3

Related Questions