2017-08-23 3 views
0

Je développe une application avec Unity et Google Tango, et une partie de mon code enregistre un fichier de description de zone (ADF) dans un thread séparé (de sorte que mon interface utilisateur reste sensible):AreaDescription.SaveCurrent() bloque la boucle de mise à jour d'Unity malgré le nouveau thread

Debug.Log("create thread"); 
m_saveThread = new Thread(() => 
{ 
    // Start saving process in another thread. 
    Debug.Log("Starting work in thread"); 
    currentAreaDescription = AreaDescription.SaveCurrent(); 
    Debug.Log("SaveCurrent completed"); 
    AreaDescription.Metadata metadata = currentAreaDescription.GetMetadata(); 
    metadata.m_name = name; 
    currentAreaDescription.SaveMetadata(metadata); 
}); 

Debug.Log("Start thread"); 
m_saveThread.Start(); 
Debug.Log("thread started"); 

Mon problème est que même quand je lance le code d'économie dans un nouveau thread, l'interface utilisateur est toujours gelé jusqu'à ce que AreaDescription.SaveCurrent() finalise. Pour confirmer cela, je l'ai ajouté l'appel d'impression suivant à mon Update():

public void Update() 
{ 
    Debug.Log("Update!"); 
    //... 
} 

Et c'est un extrait de adb logcat -s Unity au moment où je sauve:

08-23 15:11:43.746 18474 18518 I Unity : Update! 
08-23 15:11:43.747 18474 18518 I Unity : Save confirmed! 
08-23 15:11:43.747 18474 18518 I Unity : overlay 
08-23 15:11:43.747 18474 18518 I Unity : create thread 
08-23 15:11:43.748 18474 18518 I Unity : Start thread 
08-23 15:11:43.753 18474 18518 I Unity : thread started 
08-23 15:11:43.754 18474 18836 I Unity : Starting work in thread 
08-23 15:11:44.960 18474 18518 I Unity : Update! 
08-23 15:11:44.961 18474 18518 I Unity : Currently saving! 
08-23 15:11:44.964 18474 18836 I Unity : SaveCurrent completed 
08-23 15:11:44.977 18474 18518 I Unity : Update! 

(plusieurs lignes non pertinentes enlevées)

Comme le montrent les horodatages, pour l'ensemble ~ 200ms que SaveCurrent() s'exécute, Update() n'est pas appelé.

Pourquoi le thread principal est-il gelé malgré le fait que cette fonction lourde soit exécutée dans un nouveau thread? Et que puis-je faire pour le faire en cours en arrière-plan? Par ailleurs, ce code est presque directement adapté de Google's own sample repo et j'ai créé an issue à ce sujet, actuellement sans réponse.

Répondre

2

Après avoir trouvé le C API function that gets called under the hood et lire ses documents, j'ai découvert que

Depuis le service Tango verrouille en interne, les autres appels API (tels que TangoService_getPoseAtTime()) bloquent pendant l'exécution de cette méthode.

En effet, j'ai d'autres objets dans ma scène qui utilisent l'API Tango dans leurs fonctions Update(), et après l'écriture de code pour les désactiver pour le moment de la sauvegarde, l'unité ne gèle plus. Je souhaite juste qu'ils l'auraient mentionné dans le Tango docs about the Unity function I was using.

0

Sous le capot, SaveCurrent() utilise un System.Xml.Serialization.XmlSerializer qui est, selon , threadsafe.

Mais ils l'initialisent avec un StreamWriter où les membres non statiques ne sont pas threadsafe. Mais il ya TextWriter.Synchronized qui peut vous aider.

Encore pas évident pourquoi un thread séparé provoquerait le blocage de l'unité. Nous devons supposer que Unity attend que le thread finisse/ne bloque plus.

Vous pouvez essayer de pas étendre Monobehaviour, voir si l'unité cesse alors d'attendre.

Si cela ne fonctionne pas, vous devez lire volatile, et peut-être vérifier pertinents answers.unity3d thread