Как сделать Countifs в R

Unity не безопасно Thread, поэтому они решили сделать невозможным вызов своего API из другого Thread путем добавления механизма для исключения исключения, когда его API используется из другого Thread.

Этот вопрос задавали так много раз, но не было правильного решения / ответа ни на один из них. Ответы обычно «используют плагин» или делают что-то не потокобезопасное. Надеюсь, это будет последним.

Решение, которое вы обычно увидите на веб-сайте Stackoverflow или на веб-сайте Unity, - это просто использовать переменную boolean, чтобы основной поток знал, что вам нужно выполнить код в основной Thread. Это неверно, так как это не потокобезопасное и не дает вам контроля для предоставления функции вызова. Что делать, если у вас есть несколько Threads, которые должны уведомить основной поток?

Другое решение, которое вы увидите, это использовать сопрограмму вместо Thread. Это не работает. Использование сопрограммы для сокетов ничего не изменит. Вы все равно столкнетесь с проблемами замораживания . Вы должны придерживаться кода Thread или использовать Async.

Один из правильных способов сделать это - создать коллекцию, такую ​​как List. Когда вам нужно что-то выполнить в главном потоке, вызовите функцию, которая хранит код для выполнения в Action. Скопируйте List в Action в локальный List из Action, затем выполните код из локального Action в этом List, затем очистите это List. Это препятствует тому, чтобы другие Threads не дождались завершения его выполнения.

Вам также нужно добавить volatile boolean, чтобы уведомить функцию Update, что в List будет выполняться код. При копировании List в локальный List, который должен быть обернут вокруг ключевого слова lock, чтобы предотвратить запись другого потока.

Сценарий, который выполняет то, что я упомянул выше:

UnityThread Сценарий:

#define ENABLE_UPDATE_FUNCTION_CALLBACK
#define ENABLE_LATEUPDATE_FUNCTION_CALLBACK
#define ENABLE_FIXEDUPDATE_FUNCTION_CALLBACK

using System;
using System.Collections;
using UnityEngine;
using System.Collections.Generic;


public class UnityThread : MonoBehaviour
{
    //our (singleton) instance
    private static UnityThread instance = null;


    ////////////////////////////////////////////////UPDATE IMPL////////////////////////////////////////////////////////
    //Holds actions received from another Thread. Will be coped to actionCopiedQueueUpdateFunc then executed from there
    private static List actionQueuesUpdateFunc = new List();

    //holds Actions copied from actionQueuesUpdateFunc to be executed
    List actionCopiedQueueUpdateFunc = new List();

    // Used to know if whe have new Action function to execute. This prevents the use of the lock keyword every frame
    private volatile static bool noActionQueueToExecuteUpdateFunc = true;


    ////////////////////////////////////////////////LATEUPDATE IMPL////////////////////////////////////////////////////////
    //Holds actions received from another Thread. Will be coped to actionCopiedQueueLateUpdateFunc then executed from there
    private static List actionQueuesLateUpdateFunc = new List();

    //holds Actions copied from actionQueuesLateUpdateFunc to be executed
    List actionCopiedQueueLateUpdateFunc = new List();

    // Used to know if whe have new Action function to execute. This prevents the use of the lock keyword every frame
    private volatile static bool noActionQueueToExecuteLateUpdateFunc = true;



    ////////////////////////////////////////////////FIXEDUPDATE IMPL////////////////////////////////////////////////////////
    //Holds actions received from another Thread. Will be coped to actionCopiedQueueFixedUpdateFunc then executed from there
    private static List actionQueuesFixedUpdateFunc = new List();

    //holds Actions copied from actionQueuesFixedUpdateFunc to be executed
    List actionCopiedQueueFixedUpdateFunc = new List();

    // Used to know if whe have new Action function to execute. This prevents the use of the lock keyword every frame
    private volatile static bool noActionQueueToExecuteFixedUpdateFunc = true;


    //Used to initialize UnityThread. Call once before any function here
    public static void initUnityThread(bool visible = false)
    {
        if (instance != null)
        {
            return;
        }

        if (Application.isPlaying)
        {
            // add an invisible game object to the scene
            GameObject obj = new GameObject("MainThreadExecuter");
            if (!visible)
            {
                obj.hideFlags = HideFlags.HideAndDontSave;
            }

            DontDestroyOnLoad(obj);
            instance = obj.AddComponent();
        }
    }

    public void Awake()
    {
        DontDestroyOnLoad(gameObject);
    }

    //////////////////////////////////////////////COROUTINE IMPL//////////////////////////////////////////////////////
#if (ENABLE_UPDATE_FUNCTION_CALLBACK)
    public static void executeCoroutine(IEnumerator action)
    {
        if (instance != null)
        {
            executeInUpdate(() => instance.StartCoroutine(action));
        }
    }

    ////////////////////////////////////////////UPDATE IMPL////////////////////////////////////////////////////
    public static void executeInUpdate(System.Action action)
    {
        if (action == null)
        {
            throw new ArgumentNullException("action");
        }

        lock (actionQueuesUpdateFunc)
        {
            actionQueuesUpdateFunc.Add(action);
            noActionQueueToExecuteUpdateFunc = false;
        }
    }

    public void Update()
    {
        if (noActionQueueToExecuteUpdateFunc)
        {
            return;
        }

        //Clear the old actions from the actionCopiedQueueUpdateFunc queue
        actionCopiedQueueUpdateFunc.Clear();
        lock (actionQueuesUpdateFunc)
        {
            //Copy actionQueuesUpdateFunc to the actionCopiedQueueUpdateFunc variable
            actionCopiedQueueUpdateFunc.AddRange(actionQueuesUpdateFunc);
            //Now clear the actionQueuesUpdateFunc since we've done copying it
            actionQueuesUpdateFunc.Clear();
            noActionQueueToExecuteUpdateFunc = true;
        }

        // Loop and execute the functions from the actionCopiedQueueUpdateFunc
        for (int i = 0; i < actionCopiedQueueUpdateFunc.Count; i++)
        {
            actionCopiedQueueUpdateFunc[i].Invoke();
        }
    }
#endif

    ////////////////////////////////////////////LATEUPDATE IMPL////////////////////////////////////////////////////
#if (ENABLE_LATEUPDATE_FUNCTION_CALLBACK)
    public static void executeInLateUpdate(System.Action action)
    {
        if (action == null)
        {
            throw new ArgumentNullException("action");
        }

        lock (actionQueuesLateUpdateFunc)
        {
            actionQueuesLateUpdateFunc.Add(action);
            noActionQueueToExecuteLateUpdateFunc = false;
        }
    }


    public void LateUpdate()
    {
        if (noActionQueueToExecuteLateUpdateFunc)
        {
            return;
        }

        //Clear the old actions from the actionCopiedQueueLateUpdateFunc queue
        actionCopiedQueueLateUpdateFunc.Clear();
        lock (actionQueuesLateUpdateFunc)
        {
            //Copy actionQueuesLateUpdateFunc to the actionCopiedQueueLateUpdateFunc variable
            actionCopiedQueueLateUpdateFunc.AddRange(actionQueuesLateUpdateFunc);
            //Now clear the actionQueuesLateUpdateFunc since we've done copying it
            actionQueuesLateUpdateFunc.Clear();
            noActionQueueToExecuteLateUpdateFunc = true;
        }

        // Loop and execute the functions from the actionCopiedQueueLateUpdateFunc
        for (int i = 0; i < actionCopiedQueueLateUpdateFunc.Count; i++)
        {
            actionCopiedQueueLateUpdateFunc[i].Invoke();
        }
    }
#endif

    ////////////////////////////////////////////FIXEDUPDATE IMPL//////////////////////////////////////////////////
#if (ENABLE_FIXEDUPDATE_FUNCTION_CALLBACK)
    public static void executeInFixedUpdate(System.Action action)
    {
        if (action == null)
        {
            throw new ArgumentNullException("action");
        }

        lock (actionQueuesFixedUpdateFunc)
        {
            actionQueuesFixedUpdateFunc.Add(action);
            noActionQueueToExecuteFixedUpdateFunc = false;
        }
    }

    public void FixedUpdate()
    {
        if (noActionQueueToExecuteFixedUpdateFunc)
        {
            return;
        }

        //Clear the old actions from the actionCopiedQueueFixedUpdateFunc queue
        actionCopiedQueueFixedUpdateFunc.Clear();
        lock (actionQueuesFixedUpdateFunc)
        {
            //Copy actionQueuesFixedUpdateFunc to the actionCopiedQueueFixedUpdateFunc variable
            actionCopiedQueueFixedUpdateFunc.AddRange(actionQueuesFixedUpdateFunc);
            //Now clear the actionQueuesFixedUpdateFunc since we've done copying it
            actionQueuesFixedUpdateFunc.Clear();
            noActionQueueToExecuteFixedUpdateFunc = true;
        }

        // Loop and execute the functions from the actionCopiedQueueFixedUpdateFunc
        for (int i = 0; i < actionCopiedQueueFixedUpdateFunc.Count; i++)
        {
            actionCopiedQueueFixedUpdateFunc[i].Invoke();
        }
    }
#endif

    public void OnDisable()
    {
        if (instance == this)
        {
            instance = null;
        }
    }
}

ИСПОЛЬЗОВАНИЕ:

Эта реализация позволяет вам вызывать функции в 3 наиболее используемых функциях Unity: Update, LateUpdate и FixedUpdate. Это также позволяет вам вызвать функцию сопротектора в главном Thread. Он может быть расширен, чтобы иметь возможность вызывать функции в других функциях обратного вызова Unity, таких как OnPreRender и OnPostRender.

1. Сначала инициализируйте его из функции Awake().

void Awake()
{
    UnityThread.initUnityThread();
}

2.Чтобы выполнить код в главном Thread из другого потока:

UnityThread.executeInUpdate(() =>
{
    transform.Rotate(new Vector3(0f, 90f, 0f));
});

Это повернет текущий объект, к которому привязан к 90 градусам. Теперь вы можете использовать Unity API (transform.Rotate) в другом Thread.

3.Чтобы вызвать функцию в главном Thread из другого потока:

Action rot = Rotate;
UnityThread.executeInUpdate(rot);


void Rotate()
{
    transform.Rotate(new Vector3(0f, 90f, 0f));
}

Образцы # 2 и # 3 выполняются в функции Update .

4.Чтобы выполнить код в функции LateUpdate от другого Тема:

Пример этого кода отслеживания камеры.

UnityThread.executeInLateUpdate(()=>
{
    //Your code camera moving code
});

5.Чтобы выполнить код в функции FixedUpdate из другого потока :

Пример этого при выполнении физических упражнений, таких как добавление силы к Rigidbody.

UnityThread.executeInFixedUpdate(()=>
{
    //Your code physics code
});

6.Чтобы запустить функцию сопрограммы в главном Thread из другого потока :

UnityThread.executeCoroutine(myCoroutine());

IEnumerator myCoroutine()
{
    Debug.Log("Hello");
    yield return new WaitForSeconds(2f);
    Debug.Log("Test");
}

Наконец, если вам не нужно ничего выполнять в функциях LateUpdate и FixedUpdate , вы должны прокомментировать обе строки этого кода ниже:

//#define ENABLE_LATEUPDATE_FUNCTION_CALLBACK
//#define ENABLE_FIXEDUPDATE_FUNCTION_CALLBACK

Это увеличит производительность.

1
задан zx8754 27 March 2019 в 08:46
поделиться

3 ответа

d = foverlaps(df1, df2)[, .N, by = Date]
0
ответ дан lypskee 27 March 2019 в 08:46
поделиться

Если вы хотите посчитать количество строк на дату, вы можете попробовать .N

foverlaps(df1, df2)[, .(mysum = .N), by = Date ]
         Date mysum
1: 2018-01-01     7
2: 2018-01-08     7
3: 2018-01-15     7
4: 2018-01-22     7
5: 2018-01-29     2

Если вы хотите подсчитать количество уникальных значений на дату, вы можете попробовать uniqueN()

[ 111]

Оба .N и uniqueN() взяты из {data.table}.

0
ответ дан Recle Vibal 27 March 2019 в 08:46
поделиться

Вместо list(mySum = count(value)) попробуйте c(mySum = count(value)). Кодекс работает для меня тогда.

d2 <-  foverlaps(df1, df2)[, c(mySum = count(value)), by = Date ]
0
ответ дан Julian_Hn 27 March 2019 в 08:46
поделиться
Другие вопросы по тегам:

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