0

In my application have a feature like 'Sync' data, In sync operation get the data from server and stored in local sqlite database and push local data to server. When user click on sync, scene freeze up to completed the push and pull operations. How can I get out of this problem. I have tried like using separate thread for doing database operations but I am getting exception like persistance database operations work on main thread only. How can I do sync operation without freeze the screen. Please suggest any idea, Thanks in advance.

Here is the sample code I have tried

 var thread = new System.Threading.Thread(() =>
 {
     //do sqlite operations
 });

 thread.start();
Programmer
  • 121,791
  • 22
  • 236
  • 328
Deepak
  • 545
  • 1
  • 12
  • 36
  • How did you try to do it in another thread? Would something like [async / await](http://www.stevevermeulen.com/index.php/2017/09/using-async-await-in-unity3d-2017/) help you? – derHugo Aug 29 '18 at 05:11
  • @derHugo Thanks for reply. I have updated question with what I have tried for run in separate thread. – Deepak Aug 29 '18 at 05:16
  • Please give us some more information about the code you are using to sync the data and the exception you are getting – lockstock Aug 29 '18 at 11:19
  • @lockstock Thanks for reply, I have just try to save data in to local database but that data amount is huge. – Deepak Aug 29 '18 at 12:34
  • what is the exact exception message? – lockstock Aug 29 '18 at 12:38
  • This is the exception I have got. => ArgumentException: get_persistentDataPath can only be called from the main thread. Constructors and field initializers will be executed from the loading thread when loading a scene. – Deepak Aug 29 '18 at 12:39

1 Answers1

2

You should be doing expensive queries in another Thread. Once the query returns, you can use the result in the main Thread. I noticed you made attempt to use Thread but you're getting new error:

get_persistentDataPath can only be called from the main thread.

This is because you're using Application.persistentDataPath in another Thread. You cannot use most Unity API in another Thread and Application.persistentDataPath is one of them. This is a simple fix. There is no reason to use Application.persistentDataPath in another Thread. Get the value of Application.persistentDataPath and store in in a global string variable then use that global variable in the new Thread.

For example:

Don't do this ( this is what you're currently doing):

void Start()
{
    //This Start function is the main Thread (Unity's Thread)

    var thread = new System.Threading.Thread(() =>
    {
        //This is another Thread created by you

        //DO NOT DO THIS(Don't use Unity API in another Thread)
        string dbPath = Application.persistentDataPath;

        //do sqlite operations
    });
    thread.Start();
}

Do this instead (Get the variable of Application.persistentDataPath in the main thread before then use the stored value):

void Start()
{
    //This Start function is the main Thread (Unity's Thread)

    //Get path in the Main Thread
    string dbPath = Application.persistentDataPath;

    var thread = new System.Threading.Thread(() =>
    {
        //This is another Thread created by you

        //Use the path result here


        //do sqlite operations
    });
    thread.Start();
}

Finally, if you really need to use many other Unity API other than Application.persistentDataPath or for example, update the UI Text component with result from the database, you can use my UnityThread plugin which simplifies that.

public Text yourTextComponent;

void Start()
{
    UnityThread.initUnityThread();
    //This Start function is the main Thread (Unity's Thread)

    //Get path in the Main Thread
    string dbPath = Application.persistentDataPath;

    var thread = new System.Threading.Thread(() =>
    {
        //This is another Thread created by you

        //do sqlite operations

        //Show result on UI
        UnityThread.executeInUpdate(() =>
        {
            yourTextComponent.text = queryResult;
        });
    });
    thread.Start();
}
Programmer
  • 121,791
  • 22
  • 236
  • 328
  • Thanks for answer. I have fallow your suggestions as like persistence data path set in string and main thread called from another thread using 'UnityThread'. It's working great. – Deepak Aug 31 '18 at 06:49
  • I have a doubt on UnityThread i.e If I use UnityThread in loops it can executed without any problem ? – Deepak Aug 31 '18 at 06:50
  • I don't know why you doubt it. You can easily try it yourself and see if it works or not. `UnityThread` makes it easier to call Unity API from another Thread without the exception in your question. If it doesn't work, report an issue under comments in my other post and I will take a look. – Programmer Aug 31 '18 at 11:53