- Home /
Using AsyncOperation for our own services
I have a service which handles data saving / loading. The methods on this service might take a few seconds (if not more) to complete. What is the standard operating procedure for calling this service without freezing the UI?
I noticed that the "baked in" services (LoadLevelAsync) return an AsyncOperation. alowing them to easily incorporate the service into a coroutine :
ala
var async = Application.LoadLevelAsync("myLevel");
yield return async;
// continue
This is a elegant solution, and prefer this to passing an oncomplete callback into my service or messing around with a background worker. Is there any way I can acquire this pattern for my own services? If not, any solution would be helpful.
http://channel9.msdn.com/events/PDC/PDC10/FT09 Please add c#5 (I know, i know)
also, this might shred some light for you. after a long while, it did for me: http://stackoverflow.com/questions/12224602/a-method-for-making-http-requests-on-unity-ios/12606963#12606963
Answer by msknapp · Sep 25, 2011 at 04:09 AM
I personally felt that the Unity documentation on Coroutines was horrible. It took me a long time to figure out how to use them. Let me tell you one thing, do not use the .net thread classes for multi-threading, it won't work. Instead, you can write your own method that produces an IEnumerable instance. You can start a coroutine that uses that function:
Read this page to understand how to write your own function:
http://msdn.microsoft.com/en-us/library/9k7k7cf0%28v=vs.80%29.aspx
Here is my C# example:
public System.Collections.IEnumerable coroutineFunction() {
while (! doneYourPersistentProcess())
// ... wait for it ...
yield return "";
// now it is done.
doPostProcessing();
}
public void doPostProcessing() {
// your code here.
}
public void Update() {
if (userStartsPersistentProcess())
StartCoroutine(coroutineFunction());
}
public bool userStartsPersistentProcess() {
// your code here.
}
public bool doneYourPersistentProcess() {
// your code here.
}
I think your answer is correct as Richard Fine gives an insider look into Unity's Coroutines here.
I wanted to clarify that you CAN use regular threads inside of a Unity app. We use functions like System.Threading.ThreadPool.QueueUserWorkItem in our app to handle async tasks. One thing to keep in $$anonymous$$d is that some Unity operations cannot be performed outside of the main thread, such as object comparisons, so your activities are a bit limited. And any error or unhandled exception that your thread comes across will NOT be reported in the Unity log. So you'll need to handle that aspect yourself.
Answer by CasualT · Jan 09, 2013 at 08:57 PM
So here's another way of describing how to make a yieldable object:
class YieldableObject
{
public Coroutine SlowFunction()
{
return StartCoroutine(WaitForSlowFunction);
}
private IEnumerator WaitForSlowFunction()
{
while(!slowFunctionIsNotDone)
{
yield return null;
}
}
}
class MainApp()
{
IEnumerator CallingFunction()
{
YieldableObject yielder = new YieldableObject();
yield return yielder.SlowFunction(); // Will wait here for the operation to finish
}
void Main()
{
StartCoroutine(CallingFunction());
}
}
Here, Main() will start a Coroutine of CallingFunction which will create and yield to your YieldableObject while it is performing the SlowFunction. SlowFunction does whatever operation it needs to, but must have another StartCoroutine in it. The first Coroutine will pause execution and wait until the "inner" Coroutine is finished. That's the secret to getting a yield to wait for your operation to complete, similar to how Unity's built-in WWW class works.
Can you give a working example of what would be in slow function?
Hi CasualT, I was interested in your implementation but was wondering if it could be applied to my own unique code scenario. I felt the need to explain it properly so I listed it as a Separate Question Here to gain insight from you and other Unity users on some direction to the implementation I need.
Answer by dkozar · Feb 02, 2013 at 08:55 PM
There is the asynchronous way of doing things in Unity without using of coroutines. Check out the eDriven library and this video: http://www.youtube.com/watch?v=KytO48w7fOI
eDriven: https://github.com/dkozar/eDriven
Answer by nventimiglia · Aug 04, 2012 at 07:39 PM
Yeah I ran in to a similar need this week. I was cleaning up my Service Model which included several async operations (Login, GetScores, ect). Moreover these services are separate from my viewmodels which invoke them.
My solution was to expose a public IEnumerator coroutine and state variable in my service.
public class MyAccountService : MonoBehaviour
{
public bool IsAuthenticated { get; protected set; }
public IEnumerator Login()
{
yield return 1;
IsAuthenticated = true;
}
}
public class MyViewModel : MonoBehaviour
{
public MyAccountService Service;
void Awake()
{
StartCoroutine(OnReady());
}
public IEnumerator OnReady()
{
yield return 1;
yield return StartCoroutine(Service.Login());
if (Service.IsAuthenticated)
{
//blah
}
}
}
Your answer
Follow this Question
Related Questions
Saving data question 1 Answer
Threading in Unity 6 Answers
Loading screen with async load and freezing gameplay 0 Answers
Help needed with WaitForSeconds() 2 Answers
Why does accessing www.text blocks the coroutine using WWW class? 1 Answer