Try Catch in a couroutine with yield return for result

Hello everyone!

I have a WebService doing requests to a database and a proxy class on my Unity Project to call the service.

I have this snippet of code:

public IEnumerator LoginOperation()
{
try{
LoginInfo = webService.Login(Username, Password);
yield return LoginInfo;
// Do other stuff here
}
catch(Exception e)
{
Debug.Log("There was an error while contacting the Service");
Debug.LogError(e.Message);
}
}

That would do the job perfectly if it wasn’t for this error:

Cannot yield in the body of a catch clause

I need the yield return to let the loading icon spin and not freeze the client while the Service is performing the request, and still i need the try catch block to handle errors (for example if the service is offline).

How can i do that? I’ve been stuck by 2 days trying to find a solution without succeed.Thanks to everyone who will answer.

Why don’t you try this, setup a bool called noError and set it to false, then try this:

 public void LoginOperation()
 {
 try
{
 LoginInfo = webService.Login(Username, Password);
 yield return LoginInfo;
 // Do other stuff here
//if you reach the bottom of this, then change the noError to true;
 }
if(noError != true)
{
 catch(Exception e)
 {
 Debug.Log("There was an error while contacting the Service");
 Debug.LogError(e.Message);
 }
}
 }

Let me know if that works for you.

There are many misconceptions here. Coroutines represent cooperative multitasking. That requires the actual task to “cooperate” with the system. If you have a task / method that is actually blocking until it finishes there is no way to make this work with coroutines.

Coroutines are actually turned into statemachines. So they represent an object with a simple interface (IEnumerator). When you call MoveNext on that object it will actually execute the code in your original method up to the next yield instruction. When the yield instruction is reached, the MoveNext method will return. The object that was passed to the yield return statement is stored in the Current property. You don’t call MoveNext manually for coroutines. When you pass the object to StartCoroutine Unity will do that for you. Unity will determine when to resume your coroutine based on what was yielded the last time. However the actual code in the coroutine will run on the main thread like any other callback. If you block the execution you will block the whole application.

This line:

LoginInfo = webService.Login(Username, Password);

returns the login info. That means the method has to complete all the web communication before it actually can return anything. Therefore this method has to block the thread it’s running on. A method can not return something before it’s finished.

If you have blocking tasks you should actually run them on a seperate thread. This is true for most networking related things. Unity’s WWW or UnityWebRequest classes also use threads internally. They just communicate the returned data back to the main thread.

I’ve posted an example over here. However if you’re not familiar with threading you have to be careful. At no point you should allow more than one thread to access the same data as they could possibly access the data at the same time and the result is unpredictable.