Как вызывать методы с разными параметрами как Action? - PullRequest
0 голосов
/ 20 мая 2018

Я работаю над игрой в Unity, и Unity не является потокобезопасным, поэтому всякий раз, когда я делаю некоторые вычисления в другом потоке и хочу вернуться к Unity, мне нужно ставить вызовы в очередь в какую-то очередь, чтобы Unity могла выполнять эти задачи ивыполнить их в потоке Unity.Это мой код с инструментом, который выполняет свою работу:

public class Test : MonoBehaviour
{
    Thread someThread;

    private void Awake() //Executes on application start
    {
        someThread = new Thread(SomeThreadMethod);
        someThread.Start();
    }

    void SomeThreadMethod()
    {
        ExecuteInUpdate(MethodCalledNotInUnityThread);
    }

    // methods that I call from not unity thread but want to execute it IN unity thread
    void MethodCalledNotInUnityThread()
    {
        Debug.Log("Hello from UnityThread");
    }

    //--------------------------------------------------------------------------------
    //Tool for executing things in Unity Thread

    List<Action> actionQueues = new List<Action>();
    List<Action> actionCopiedQueue = new List<Action>();

    private volatile static bool noActionQueue = true;

    public void ExecuteInUpdate(Action _action)
    {
        lock (actionQueues)
        {
            actionQueues.Add(action);
            noActionQueue = false;
        }
    }

    public void Update()//runs all time, sort of while(true) loop in unity thread
    {
        if (noActionQueue)
        {
            return;
        }

        actionCopiedQueue.Clear();

        lock (actionQueues)
        {
            actionCopiedQueue.AddRange(actionQueues);
            actionQueues.Clear();
            noActionQueue = true;
        }

        for (int i = 0; i < actionCopiedQueue.Count; i++)
        {
            actionCopiedQueue[i]();
        }
    }
}

Но проблема в том, что он работает только с методами, которые не принимают параметров.Если бы я создал такой метод, как:

    void MethodCalledNotInUnityThread1(int _arg)
    {
        Debug.Log("Hello from UnityThread" + _arg);
    }

, я бы не смог его вызвать, потому что у него есть параметр.Я пытался работать с Action с универсальным параметром, таким как

    Action<int> action

, но тогда я могу передавать только методы, которые принимают только один параметр, и это int.У меня есть много методов, которые принимают параметры diffenet в разных количествах, так как мне это сделать?

Я хочу добиться чего-то подобного:

    Dictionary<Action, object[]> paramsForAction = new Dictionary<Action, object[]>();

    public void ExecuteInUpdate(Action _action, params object[] _args)
    {
        paramsForAction.Add(action, args);//save params for action

        //add action to queue
    }

    public void Update()
    {
        //find action to execute

        object[] args = paramsForAction[actionToExecute];//get params for action
        actionToExecute(args);

    }

Конечно, это не работает и делаетнет смысла, но, надеюсь, ты сможешь понять, что я пытаюсь сделать.

Ответы [ 2 ]

0 голосов
/ 20 мая 2018

Вы также можете просто использовать Action<T>, где T - первый параметр метода.Тогда есть также Action<T1, T2> для двух параметров и т. Д.

И если вам нужен тип возвращаемого значения, Func<TResult> - это точно такая же идея, но с типом возвращаемого типа.Func<TResult, TParam1> и т. Д.

0 голосов
/ 20 мая 2018

Просто оберните ваш вызов метода в лямбда-выражение:

Action act = () => MethodCalledNotInUnityThread1(argVal1, argVal2); ExecuteInUpdate(act);

...