Вы можете зарегистрировать обработчик для 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}));
просто поместите ваш цикл 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
}
Я думаю, что вы можете использовать что-то вроде
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 .
Я получил следующее решение. Я не нашел способа загрузить основной поток необработанных файлов, но мне удалось загрузить его в 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
});