Eu tinha uma rotina no Unity3D que baixava um zip de um servidor, extraia-o no caminho de dados persistentes e carregava seu conteúdo na memória. O fluxo ficou mais ou menos assim:
IEnumerator LongCoroutine()
{
yield return StartCoroutine(DownloadZip());
ExtractZip();
yield return StartCoroutine(LoadZipContent());
}
Mas o ExtractZip()
método (que usa a biblioteca DotNetZip), é síncrono, leva muito tempo e não me deixa lugar para ceder durante o processo.
Isso resultava na morte do aplicativo (em dispositivos móveis) sempre que eu tentava extrair um zip grande, o que eu assumo ser devido ao fato de o thread principal ficar sem resposta por muito tempo.
Isso é algo que o sistema operacional móvel sabe fazer (interrompa o aplicativo se um quadro demorar muito)?
Portanto, presumi que extrair o zip em um thread separado poderia resolver o problema e parece ter funcionado. Eu criei esta classe:
public class ThreadedAction
{
public ThreadedAction(Action action)
{
var thread = new Thread(() => {
if(action != null)
action();
_isDone = true;
});
thread.Start();
}
public IEnumerator WaitForComplete()
{
while (!_isDone)
yield return null;
}
private bool _isDone = false;
}
E eu uso assim:
IEnumerator LongCoroutine()
{
yield return StartCoroutine(DownloadZip());
var extractAction = new ThreadedAction(ExtractZip);
yield return StartCoroutine(extractAction.WaitForComplete());
yield return StartCoroutine(LoadZipContent());
}
Mas ainda não tenho certeza se essa é a melhor maneira de implementá-lo ou se preciso bloquear _isDone
(não estou acostumado a multithreading).
Alguma coisa pode dar errado com isso / estou perdendo alguma coisa?
fonte
Você não precisa bloquear _isDone, mas precisa ser marcado como volátil.
fonte