Forum Scripting Message Error in Unity client code

Post your problems and discussions relating to scripting in Unity here.

Message Error in Unity client code

Postby capitaljmedia » November 9th, 2011, 8:37 pm

Hello,

I'm receiving this error:

Code: Select all
InvalidOperationException: Collection was modified; enumeration operation may not execute.
System.Collections.Generic.List`1+Enumerator[PlayerIOClient.Message].VerifyState ()
System.Collections.Generic.List`1+Enumerator[PlayerIOClient.Message].MoveNext ()


It occurs in Unity in what looks like the ForEach loop that processes messages.

Code: Select all
foreach(PlayerIOClient.Message m in msgList)


It is not consistent and happens probably around 10% of the time. The code is the same as in the Mushrooms unity example. The game is still in development and using a development server. I haven't noticed any particular pattern or reaction to a specific message that is being received. Is it because a message was received while other messages were being processed?

-J
capitaljmedia
 
Posts: 29
Joined: September 13th, 2011, 2:33 am

Re: Message Error in Unity client code

Postby RocketBunny » November 15th, 2011, 11:29 am

Can you post the code snipped for the loop that is throwing this error?

Are you modifying the collection (like removing elements) midway through the enumeration?

-Rob.
RocketBunny
Paid Member
 
Posts: 23
Joined: June 16th, 2010, 9:49 pm

Re: Message Error in Unity client code

Postby capitaljmedia » November 15th, 2011, 6:45 pm

Hi,

No, I'm not modifying the collection in the loop. The whole message handling loop is exactly the same as in the Unity demo project that comes with PlayerIO.

Code: Select all
void FixedUpdate() {
      // process message queue
                foreach(PlayerIOClient.Message m in msgList) {
            switch(m.Type) {
            case "setup_complete":
               // the game is setup, ready to fetch playerObject
               ConnectionComplete();
               break;
                              ...... more case statements...
                        // clear message queue after it's been processed
         msgList.Clear();
      }
capitaljmedia
 
Posts: 29
Joined: September 13th, 2011, 2:33 am

Re: Message Error in Unity client code

Postby RocketBunny » November 15th, 2011, 10:50 pm

Assuming that it might be the list being modified outside of the iterator, try removing the iterator by changing this line

Code: Select all
foreach(PlayerIOClient.Message m in msgList) {


to this

Code: Select all
while( msgList.Count>0 ) {
   PlayerIOClient.Message m = msgList[0];
   msgList.RemoveAt(0);


This will at least determine if it is indeed the iterator that is being trashed.

-Rob.
RocketBunny
Paid Member
 
Posts: 23
Joined: June 16th, 2010, 9:49 pm

Re: Message Error in Unity client code

Postby capitaljmedia » November 15th, 2011, 10:52 pm

Good idea, thanks I'll give that a try.

-JJ
capitaljmedia
 
Posts: 29
Joined: September 13th, 2011, 2:33 am

Re: Message Error in Unity client code

Postby Henrik » November 16th, 2011, 3:46 pm

capitaljmedia wrote:Is it because a message was received while other messages were being processed?

Yes. Welcome to the wonderful world of race conditions! :-D

The simplest way to solve this problem is to put a lock around the msgList so that access to it is synchronized. To do that, put this around all code that modifies it or iterates through it:

Code: Select all
lock(msgList) {
    //...
}
Henrik
.IO
 
Posts: 1880
Joined: January 4th, 2010, 1:53 pm

Re: Message Error in Unity client code

Postby capitaljmedia » November 17th, 2011, 6:17 am

Thanks Henrik, I'll give that a try :)
capitaljmedia
 
Posts: 29
Joined: September 13th, 2011, 2:33 am

Re: Message Error in Unity client code

Postby deadbug » April 9th, 2012, 12:44 am

I would like to propose a simple fix to this:

At the start of FixedUpdate, put in a var tmpList = new List<Message>(msgList); msgList.Clear() and iterate over this tmpList instead.

The reason for this 'little' error above is that the Player.IO unity library is actually violating some core Unity requirements by running under the missassumption that Unity is a .NET technology fulling all standard .NET practices it seems.
Yet Unity violates a few of them, namely Unity is not thread nor async callback save at all as it runs on the native C / C++ layer with Mono only being present for scripting (thats why delegates can not touch UnityEngine.Object extending things or you get exceptions).
In detail: Player.IO calls the message handling function from its own thread, which adds the object to the list, while Unity is still iterating over it within Update.

Using locks here is pretty granted not to help much as locking FixedUpdate / LateUpdate / Update is a very bad idea as FixedUpdate / Update / LateUpdate are fired when they are meant to happen, independent if 1+ previous calls are still locked. Its crucial to keep in mind that Unity also neither respects nor even checks locks for its own stuff as it can never happen from its design PoV with all running within a single (the main) thread of the application.
deadbug
 
Posts: 35
Joined: November 1st, 2011, 1:35 am


Return to Scripting



cron