Android Unity - загрузка файла в фоновом потоке

UPDATE:

Вы можете зарегистрировать обработчик для process.on('exit') и в любом другом случае (SIGINT или необработанное исключение) для вызова process.exit()

process.stdin.resume();//so the program will not close instantly

function exitHandler(options, exitCode) {
    if (options.cleanup) console.log('clean');
    if (exitCode || exitCode === 0) console.log(exitCode);
    if (options.exit) process.exit();
}

//do something when app is closing
process.on('exit', exitHandler.bind(null,{cleanup:true}));

//catches ctrl+c event
process.on('SIGINT', exitHandler.bind(null, {exit:true}));

// catches "kill pid" (for example: nodemon restart)
process.on('SIGUSR1', exitHandler.bind(null, {exit:true}));
process.on('SIGUSR2', exitHandler.bind(null, {exit:true}));

//catches uncaught exceptions
process.on('uncaughtException', exitHandler.bind(null, {exit:true}));
1
задан Michał Powłoka 17 January 2019 в 11:00
поделиться

3 ответа

просто поместите ваш цикл while внутри CoRoutine, и пока ваш запрос не будет обработан до возврата дохода. когда это будет сделано, вызовите метод, в котором вы хотите использовать свои данные:

IEnumerator MyMethod()
{
    var reader = new WWW(filePath);
    while (!reader.isDone) 
    { 
        yield return; // <- use endofFrame or Wait For ore something else if u want
    }
    LoadingDoneDoData(reader.bytes);
}

void LoadingDoneDoData(bytes[] data)
{
    // your Code here
}
0
ответ дан Vampirasu 17 January 2019 в 11:00
поделиться

Я думаю, что вы можете использовать что-то вроде

public static async void ReadAllBytes(string filePath, Action<byte[]> successCallback)
{
    byte[] result;
    using (FileStream stream = File.Open(filePath, FileMode.Open))
    {
        result = new byte[stream.Length];
        await stream.ReadAsync(result, 0, (int)stream.Length);
    }

    // Now pass the byte[] to the callback
    successCallback.Invoke();
}

( Источник )

Чем, я думаю, вы можете использовать его как

TheClass.ReadAllBytes(
    "a/file/path/",

    // What shall be done as soon as you have the byte[]
    (bytes) =>
    {
        // What you want to use the bytes for
    }
);
[1111 ] Я не эксперт по многопоточности, но здесь , а также здесь вы можете найти больше примеров и инструкций для async - await с Unity3d.


В качестве альтернативы вам может быть также интересна новая Unity Jobsystem .

0
ответ дан derHugo 17 January 2019 в 11:00
поделиться

Я получил следующее решение. Я не нашел способа загрузить основной поток необработанных файлов, но мне удалось загрузить его в Coroutine и выполнить дальнейшие (также тяжелые) операции с этим файлом в фоновом потоке. Я сделал статический метод, подобный этому:

public static void ReadAllBytesInCoroutine(MonoBehaviour context, string filePath, Action<ReadBytesInCoroutineResult> onComplete)
{
    context.StartCoroutine(ReadFileBytesAndTakeAction(filePath, onComplete));
}

private static IEnumerator ReadFileBytesAndTakeAction(string filePath, Action<ReadBytesInCoroutineResult> followingAction)
{
    WWW reader = null;

    try
    {
        reader = new WWW(filePath);
    }
    catch(Exception exception)
    {
        followingAction.Invoke(ReadBytesInCoroutineResult.Failure(exception));
    }

    while (reader != null && !reader.isDone)
    {
        yield return null;
    }
    followingAction.Invoke(ReadBytesInCoroutineResult.Success(reader.bytes));
}

ReadBytesInCoroutineResult - это мой простой, настраиваемый класс данных:

public class ReadBytesInCoroutineResult
{
    public readonly bool successful;
    public readonly byte[] data;
    public readonly Exception reason;

    private ReadBytesInCoroutineResult(bool successful, byte[] data, Exception reason)
    {
        this.successful = successful;
        this.data = data;
        this.reason = reason;
    }

    public static ReadBytesInCoroutineResult Success(byte[] data)
    {
        return new ReadBytesInCoroutineResult(true, data, null);
    }

    public static ReadBytesInCoroutineResult Failure(Exception reason)
    {
        return new ReadBytesInCoroutineResult(true, null, reason);
    }

}

Таким образом, у меня есть механизм заказа загрузки файла в сопрограмме в любое место (пока оно находится в главном потоке). Файл загружается синхронно, но он не блокирует основной поток из-за сопрограммы. Позже я вызываю эту функцию и беру полученные байты в отдельный поток, где я выполняю тяжелые вычисления на них.

    ResourcesUtils.ReadAllBytesInCoroutine(monoBehavior, filePath, (bytes) => {

        //here I run an async method which takes bytes as parameter

    });
0
ответ дан Michał Powłoka 17 January 2019 в 11:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: