How do I run a coroutine in the non-main thread?

I want to run saves to my database periodically instead of every time the data is updated. I want to run it sort of like a garbage collection routine. Sleep X seconds, run, sleep X seconds, run.

I tried using repeatInvoking first but it can only run from the main thread. So then I decided to use a coroutine. It works fine as long as I don’t put in the yield statement, but as soon as I add Yield it simply does not run.

in Awake()

savePis = new Thread(DoSaves);
savePis.Start();

void DoSaves()

{
    Debug.Log("Calling SaveToDB ");
    SaveToDB(); // because you cannot start a thread with an IEnumerator
}

IEnumerator SaveToDB()
{
    Debug.Log("STARTING SAVETODB....");
    Debug.Log("YEILDING ..... ");
    yield return new WaitForSeconds(1);        // because invoke repeating only works in the main thread
    Debug.Log("FINISHED YEILDING");
}

The Debug.Log never prints Starting SaveToDB. But if I switch the yield statement for a return null, it prints out great.

I’m not calling ANY unity APIs here so why is the yield failing? I thought it might be Debug.Log that was failing, but changing them to print doesn’t help.

I understand that this is a 9 year old post, but I had this question recently as I am retrieving large data from my database and the current answer isn’t adequate.

public void GetUserInfo()
{
    new System.Threading.Thread(GetData).Start();

    void GetData()
    {
        StartCoroutine(GetUser((UserData user) =>
        {
            ClockController.instance.SetUserData(user);
        }));
    }
}

I’m a little curious why you are pushing this operation to another thread?

But for starters, the delayed execution functionality of yield that Unity only works if you call it from StartCoroutine(). Otherwise it’s just a regular C# yield. You can still yield return WaitForSeconds, it just won’t do anything meaningful.

I would recommend keeping time in the main thread then pushing this save feature over to a second thread only when you need it.

void Start () {
      StartCoroutine( SaveToDB() );
}

IEnumerator SaveToDB () {

     while (true) {
           yield return new WaitForSeconds(1);
           savePis = new Thread(DoSaves);
           savePis.Start();
     }
}

That’s just a quick set up. I’d probably use the thread pool over creating a new thread, but you probably know your system better than me.