What is wrong

If you are developing with Unity 3D, coroutines are part of your life. Exceptions are also. It sounds trivial, but it is not easy to bring together both of these things. Consider:

1 public IEnumerable SomeCoroutine()
2 {
3     yield return foo;
4     yield return bar;
5 }

One of the natural ways to handle general exception is to surround it with try..catch:

1 public IEnumerable SomeCoroutine()
2 {
3    try {
4         yield return foo;
5         ...
6         yield return bar;
7         ....
8    } catch { ... }
9 }

Looks nice, right?

No, it doesn’t. It won’t even compile. We need to get rid of yield from block to get it to work:

 1 public IEnumerable SomeCoroutine()
 2 {
 3 
 4    yield return foo;
 5 
 6    try {
 7      ...
 8    } catch { ... }
 9 
10    yield return bar;
11 
12    try {
13      ...
14    } catch { ... }
15 }

Shit, not what I looked for…

Solution

In order to handle this strange case I have created a wrapper

 1 public class CoroutineExceptionCatcher : IEnumerator
 2 {
 3     private readonly IEnumerator wrapped;
 4     private readonly Action<Exception> handler;
 5 
 6     public CoroutineExceptionCatcher(IEnumerator wrapped, Action<Exception> handler)
 7     {
 8         this.wrapped = wrapped;
 9         this.handler = handler;
10     }
11 
12     public bool MoveNext()
13     {
14 
15         try
16         {
17             return this.wrapped.MoveNext();
18         }
19         catch (Exception ex)
20         {
21             if (this.handler == null) throw ex;
22 
23             this.handler(ex);
24             return false;
25         }
26     }
27 
28     public void Reset()
29     {
30         this.wrapped.Reset();
31     }
32 
33     public object Current
34     {
35         get { return this.wrapped.Current; }
36     }
37 }

Usage is very simple:

1 StartCoroutine(new CoroutineExceptionCatcher(
2       MyCoroutine().GetEnumerator(),
3       exception =>
4             {
5                  Debug.LogError(
6                  "Fatal error: " + exception.Message
7                    + ", stacktrase: " + exception.StackTrace);
8             }));

Nice, right?


Patryk Wąsiewicz

A very casual blog about programmer's life.