Постоянно сталкиваюсь с ошибкой :
UnityException: GetAssetPath can only be called from the main thread.
Constructors and field initializers will be executed from the loading thread when loading a scene.
Мне надо выполнить метод AssetDatabase.GetAssetPath(GamObjArrayTexture[i]);, на котором обрывается всё выполнение кода, так как это не основной поток. Эти советы тоже не помогают :
List<string> listStringUrlTexture = new List<string>();
string path;
Thread thread = new Thread(() => { AssetDatabase.GetAssetPath(GamObjArrayTexture[i]); });
thread.Start();
listStringUrlTexture.Add(path);
Так как у меня всё это выполняется не в основном потоке.
Как мне переписать код с потоками, чтоб когда выполнялся метод (который возвращает значение) не выкидывал ошибок?
Мой код :
private Worker _worker;
public static bool pressedbool = false;
private Thread _thread;
private UnityEngine.Object _locker;
public static int _progress;
com.youvisio.BackgroundWorker _backgroundWorker;
public string InfoStr;
void DrawFooter()
{
GUILayout.BeginArea(FooterSection);
GUILayout.BeginVertical();
if (!pressedbool)
{
GUILayout.Label("Выберите json");
GUILayout.BeginHorizontal();
stringTextFieldURLjsonfile = GUILayout.TextField(stringTextFieldURLjsonfile);
if (GUILayout.Button("Обзор...", GUILayout.Width(100)))
{
stringTextFieldURLjsonfile = EditorUtility.OpenFilePanel("Выбрать json", "", "json");
}
GUILayout.EndHorizontal();
if (GUILayout.Button("Старт"))
{
if (TerrainList != null && TerrainList.Count() > 0)
{
pressedbool = true;
_worker = new Worker();
_worker.ProcessChanged += worker_ProcessChanged;
_worker.WorkCompleted += worker_WorkCompleted;
_worker.WorkLog += worker_Log;
_worker.myList = myList;
_worker.count_list_index = count_list_index;
_worker.GamObjArrayTexture = GamObjArrayTexture;
_worker.TerrainList = TerrainList;
_worker.brushsize = brushsize;
Worker._cancelled = false;
// _thread = new Thread(() => _worker.ProcessJSONPlaceONmapTextures("", null));
// _thread.IsBackground = true;
_thread = new Thread(_worker.Work);
// if (count_list_index >= 0)
// {
// if (myList[count_list_index].geometry_type == 0)
// {
// ProcessJSONPlaceONmapTextures();
// }
// else if (myList[count_list_index].geometry_type == 1)
// {
// // ProcessJSONPlaceONmap();
// }
// }
_locker = new UnityEngine.Object();
_progress = 0;
_thread.Start();
}
else
{
Debug.Log("Terrain List пуст. Назначьте террейны.");
}
}
}
else
{
if (GUILayout.Button("Стоп"))
{
pressedbool = false;
Worker.Cancel();
}
if (_backgroundWorker != null) _backgroundWorker.Update();
EditorGUI.ProgressBar(new Rect(3, 45, FooterSection.width - 6, 20), _progress / 100.0f, "progress: " + _progress + "%");
}
GUILayout.EndVertical();
GUILayout.EndArea();
}
// IEnumerator LoadingRoutine()
// {
// while (_thread.IsAlive)
// {
// lock (_locker)
// {
// _progress = EditorGUILayout.IntSlider(Rect(3, 3, position.width - 6, 15), "progress:", _progress, 0, 100);
// }
// yield return null;
// }
// }
public static void worker_WorkCompleted(bool cancelled)
{
Action action = () =>
{
string messeg = cancelled ? "Процесс отменён" : "Процесс завершён!";
Debug.Log("messeg=" + messeg);
pressedbool = false;
};
action();
// if (InvokeRequired)
// Invoke(action);
// else
// action();
}
public static void worker_ProcessChanged(int progress)
{
Action action = () => { _progress = progress; };
// if (InvokeRequired)
// Invoke(action);
// else
// action();
action();
}
public static void worker_Log(string str)
{
Action action = () => { Debug.Log(str); };
// if (InvokeRequired)
// Invoke(action);
// else
// action();
action();
}
void OnInspectorUpdate()
{
Repaint();
}
Класс worker(выполняется в дочернем потоке):
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Runtime.CompilerServices;
internal class Worker
{
public static bool _cancelled = false;
public List<Terrain> lstTerrain = null;
public List<string> listStringUrlTexture = null;
public List<int> idtexture = null;
public List<mapObject> myList = null;
public int count_list_index = -3;
public Texture2D[] GamObjArrayTexture = null;
public Terrain[] TerrainList = new Terrain[0];
public float brushsize = 3;
public static void Cancel()
{
_cancelled = true;
}
public void Work()
{
for (int i = 0; i <= 100; i++)
{
if (_cancelled) break;
// if (a.IsCanceled) return;
Thread.Sleep(50);
Debug.Log("обрабатывается...");
marijnz.EditorCoroutines.PlacementObjects.worker_ProcessChanged(20);
if (templstTerrain != null)
{
lstTerrain = templstTerrain;
}
else
{
lstTerrain = TerrainList.OfType<Terrain>().ToList();
}
if (TerrainList != null && TerrainList.Count() > 0)
{
marijnz.EditorCoroutines.PlacementObjects.worker_ProcessChanged(0);
listStringUrlTexture = getListStringUrlTexture();
marijnz.EditorCoroutines.PlacementObjects.worker_ProcessChanged(25);
}
marijnz.EditorCoroutines.PlacementObjects.worker_ProcessChanged(i);
}
marijnz.EditorCoroutines.PlacementObjects.worker_WorkCompleted(_cancelled);
}
public event Action<int> ProcessChanged;
public event Action<bool> WorkCompleted;
public event Action<string> WorkLog;
}
public static List<string> getListStringUrlTexture()
{
List<string> listStringUrlTexture = new List<string>();
// List<Thread> listThreads = new List<Thread>();
for (int i = 0; i < GamObjArrayTexture.Length; i++)
{
if (GamObjArrayTexture[i] != null)
{
string path = AssetDatabase.GetAssetPath(GamObjArrayTexture[i]);
listStringUrlTexture.Add(path);
}
}
foreach (var singlValueList in listStringUrlTexture)
{
Debug.Log(singlValueList);
}
return (listStringUrlTexture.Count > 0) ? listStringUrlTexture : null;
}
Как отправить в main thread выполнение getListStringUrlTexture() метода?
Ответ я опубликовал тут. В краце класс Dispatcher помогает избежать ошибок типа :
UnityException: GetAssetPath can only be called from the main thread.
Constructors and field initializers will be executed from the loading thread when loading a scene.
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Через fetch в файл сorephp отправляется action, который равен 'login', а так же email и epass
Во время нажатия кнопки Start Server загорается зеленый круг на Apache,через 1 секунду уже на MySQL,затем с Apache пропадает зеленый круг и остается только...