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.
public void LoginOperation()
{
try
{
LoginInfo = webService.Login(Username, Password);
}
catch(Exception e)
{
Debug.Log("There was an error while contacting the Service");
Debug.LogError(e.Message);
}
yield return LoginInfo;
try {
// Do other stuff here
}
catch(Exception e)
{
Debug.Log("There was an error while contacting the Service");
Debug.LogError(e.Message);
}
}
Hello and thanks for reply!
I’ve noticed a thing:
If i modify the code in this way :
public void LoginOperation()
{
try
{
LoginInfo = webService.Login(Username, Password);
LoginInfo = webService.Login(Username, Password);
LoginInfo = webService.Login(Username, Password);
// Other 200+ lines like the ones above
}
catch(Exception e)
{
Debug.Log("There was an error while contacting the Service");
Debug.LogError(e.Message);
}
yield return LoginInfo;
Debug.Log("All done!");
}
The application freezes waiting for the requests, actually i have a Debug.Log in the Update function that doesn’t show logs while the requests are being transferred and performed but they resume as soon as “All Done” is being logged.
So for a guess, does it also freezes for just one request but i don’t see it because it’s very fast?
Also, 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).
If you enable 4.x runtime in unity 2018 or later you can use tasks but they have nothing todo with coroutines, but they solve same problem running async code in a sync manner. Do your wcf client have old style async methods?
They often had a method called BeginAsync or similar which started the operation in a none blocking manner than you polled the completion state. You can use that from a corotuine.
Thank you answers they’re helping me alot.
I cannot use 4.x runtime due it causes me some errors with the System.ServiceModel dll.
So what i did was to execute this svcutil command to generate the proxyclass:
svcutil -out:MyService.cs http://localhost/?wsdl
I red that for making async methods you should add
svcutil -out:MyService.cs http://localhost/?wsdl /a
This actually gives me a “Begin” method that i don’t know how to use since it asks for an AsyncCallback and a object), plus i don’t have the “Method” with the “Async” suffix generated.
I red that for doing that you should launch this command
svcutil -out:MyService.cs http://localhost/?wsdl /a /tcv:Version35
But it generates me this error
Mono service contract conversion tool 0.1.0.0 - Copyright (C) 2006 Novell, Inc.
Attempting to download metadata from 'http://localhost/?wsdl' using DISCO..
Disco found documents at the following URLs:
- Xml Schema at http://localhost/?xsd=xsd2
- Xml Schema at http://localhost/?xsd=xsd1
- WSDL document at http://localhost/?wsdl
- Xml Schema at http://localhost/?xsd=xsd0
Unhandled Exception: System.NotSupportedException: Not supported file extension:
at Mono.ServiceContractTool.Driver.Run(String[] args)
at Mono.ServiceContractTool.Driver.Main(String[] args)
Please help me, I’m struggling with this from 2 days and since i woke up this morning.
__**__ **With the code above everything works fine, i can get the result and all is good.** **With this code** **csharp
** public IEnumerator LoginOperation()
{
client.Login += MyClient_LoginCompleted;
client.LoginAsync();
yield return null;
}
private void MyClient_LoginCompleted(object sender, LoginCompletedEventArgs e)
{
Debug.Log("completed");
if (e.Error.Message != null)
Debug.Log("there was an error");
else
Debug.Log(e.Result);
}**
``` For some strange reason i only get the “completed” log without the last e.Result log… I can’t even imagine why this is happening…
You can’t use the unity framework outside the main thread. You can set a bool to true and wait for that in the corot. You can also switch to a rest service and use the built in functions for rest
If that is, what i did was to make a copy of that class (it seems i’m allowed to do that) from the thread to Unity, and now i have a copy of that information usable by the unity framework.
It’s a bit hacky. I would probably handle it inside a coroutine using a local event handler in that corot method. Or write a custom yield instruction.
Thank you so much for your replyes, you can-t imagine how i’m appreciating it, also that you’re sharing your time with me.
But i didn’t understood that snippet of code…
MyCorot is basically my public IEnumerator LoginOperation() ?
Service.Completed is my “client.LoginCompleted += SopClient_LoginCompleted;”.?
If so i didn’t understood that line at all: Service.Completed += (o, r) => result = r;
What is o? what is r? And result?
Sorry but i didn’t understood and i would love to do it in that way, without having multiple methods and classes like SopClient_LoginCompleted for every request i have to make.