Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by BouncedPhysical · Jul 12, 2019 at 03:48 PM · issuecoroutineswebservice

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.

Comment
Add comment · Show 4
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Hellium · Jul 12, 2019 at 03:59 PM 0
Share

I am not sure which line could throw the error. Not sure it's the yield return LoginInfo, is it?

avatar image BouncedPhysical Hellium · Jul 12, 2019 at 04:10 PM 0
Share

Yes it is it. But i've noticed a thing.

With this code (without any try/catch blocks):

 public IEnumerator LoginOperation() {
 LoginInfo = webService.Login(Username, Password);
 yield return LoginInfo;
 }

If i put a System.Threading.Thread.Sleep(5000) in the Login function of the webservice to slow it down, Unity waits for it before doing everything else (also the icon animation on the canvas is blocked waiting for the request).

What should i do?

avatar image TreyH · Jul 12, 2019 at 04:35 PM 1
Share

This isn't a coroutine or a function declared as an IEnumerator return type, so those yields aren't going to compile anyway.

You'd need to set up that function as returning IEnumerator ins$$anonymous$$d of void. As for your question, they can't return anything anyway so you'd also want to set up some sort of callback to pass that info for you.

avatar image BouncedPhysical TreyH · Jul 12, 2019 at 05:51 PM 0
Share

Hello TreyH. Thank you for your replies, they're helping me alot

So currently I've modified the LoginOperation from the WCF Service from

     public LoginInfo LoadingOperation(string Username, string Password) 
     {
     LoginInfo loginInfo = new LoginInfo();
     loginInfo.username = "X";
     return loginInfo;
     }



To:

     public IEnumerator<LoginInfo> LoadingOperation(string Username, string Password) 
     {
     LoginInfo loginInfo = new LoginInfo();
     loginInfo.username = "X";
     Console.WriteLine("returning");
     yield return loginInfo;
     }


But when i call it from Unity also in this way (just to test if it works)

 public IEnumerator LoginInGame()
         {
             yield return sopClient.Login(1, "55");
         }



I get:

SocketException: An existing connection was forcibly closed by the remote host.



Please could you help me further? I feel like it is the right direction but i do not know how to proceed.

2 Replies

· Add your reply
  • Sort: 
avatar image
0

Answer by I_Am_Err00r · Jul 12, 2019 at 04:13 PM

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.

Comment
Add comment · Show 5 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image BouncedPhysical · Jul 12, 2019 at 04:19 PM 0
Share

Thank you for your reply but if i use a void i'm not able to call yield return on LoginInfo.

Also, i've noticed a thing.

With this code (without any try/catch blocks):

  public IEnumerator LoginOperation() {
  LoginInfo = webService.Login(Username, Password);
  yield return LoginInfo;
  }

If i put a System.Threading.Thread.Sleep(5000) in the Login function of the webservice to slow it down, Unity waits for it before doing everything else (also the icon animation on the canvas is blocked waiting for the request).

What should i do?

avatar image I_Am_Err00r BouncedPhysical · Jul 12, 2019 at 04:24 PM 0
Share

I use bools in coroutines and setting the bool variable to false by default will still let you to change to true in that check you are running before it hits that catch part of the script; encapsulating the catch part of your code in that if statement should separate it from your yield return error. Have you tried my suggestion?

avatar image BouncedPhysical I_Am_Err00r · Jul 12, 2019 at 04:30 PM 0
Share

Yes i did.

But it's look like the Coroutine is not running async and it causes the whole application to freeze while waiting for the response.

avatar image TreyH BouncedPhysical · Jul 12, 2019 at 04:37 PM 1
Share

Coroutines don't add threading to your project btw, and iirc they're closer to how the JS event loop works. Having a coroutine do something like while (true); will freeze your project as it will never yield control back.


Your login system needs to use a coroutine friendly mechanism or you need to set it up using the builtin UnityWebRequest class.

avatar image BouncedPhysical TreyH · Jul 12, 2019 at 05:14 PM 1
Share

Thanks for the reply, i did some digging and discovered that this is the problem.

But how could i setup a WCF service to use UnityWebRequest?

avatar image
0

Answer by Bunny83 · Jul 12, 2019 at 06:34 PM

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.

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

111 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

[Solved] Camera issue - Do not see camera icon in scene 1 Answer

My built in ads extension stopped working after updating unity? How can I fix this? 1 Answer

Raycast not Detecting Colliders 2 Answers

Wierd behaviour of slider when value is changed too fast 1 Answer

Firebase Remote Config BUG 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges