Вызов C # обратного вызова в отдельном потоке через PInvoke - PullRequest
0 голосов
/ 29 марта 2019

Я пытаюсь выполнить обратный вызов через PInvoke из управляемой программы на C # в собственную C ++ DLL. Эти обратные вызовы могут быть вызваны после больших задержек в отдельном потоке. Моя текущая конструкция заключается в том, что обратный вызов вызывается правильно с правильными данными, если вызывается немедленно на собственном уровне, но происходит сбой, если вызывается с задержкой в ​​отдельном потоке. Вот простой пример настройки:

Интерфейс C #

public class Example
{
    private delegate void NativeLoginCallback(IntPtr bytes);

    [DllImport ("NativeExample")]
    private static extern void Example_loginAsync(NativeLoginCallback callback);

    private delegate void LoginCallback(string data);
    public void LoginAsync(LoginCallback callback)
    {
        NativeLoginCallback nativeCallback = (IntPtr bytes) =>
        {
            string data = MarshalUtility.Deserialize<string>(bytes);
            try
            {
                callback(data);
            }
            catch (Exception ex)
            {
                Debug.Log(ex);
            }
        }

        Example_loginAsync(nativeCallback);
    }
}

Интерфейс C

extern "C" __declspec(dllimport) void Example_loginAsync(void* callback)
{
    typedef void(*CSharpLoginCallbackType)(void* data);
    CSharpLoginCallbackType csharpCallback = (CSharpLoginCallbackType) callback;

    auto cppLoginCallback = [csharpCallback](std::string data)
    {
        std::this_thread::sleep_for(std::chrono::milliseconds(5000));

        unsigned char* dataBytes;
        MarshalUtility::Serialize(data, dataBytes);
        csharpCallback(dataBytes);
    };

    std::string testData = "This one is called immediately on same thread.";
    unsigned char* testDataBytes;
    MarshalUtility::Serialize(testData, testDataBytes);
    csharpCallback(testDataBytes);

    std::thread t(cppLoginCallback, "This one is called after 5 seconds on seperate thread.");
    t.detach();
}

C # Caller

public class ExampleIntegrator
{
    Example example = new Example();

    public void Test()
    {
        example.Login((string data) =>
        {
            Debug.Log(data);
        };
    }

};

Вывод, который я вижу:

This one is called immediately on same thread.
NullReferenceException

Вывод, который я ожидаю:

This one is called immediately on same thread.
This one is called after 5 seconds on seperate thread.

При проверке я обнаружил, что данные в области действия NativeLoginCallback верны, т.е. после строки string data = MarshalUtility.Deserialize<string>(bytes); отладчик правильно показывает Эта функция вызывается через 5 секунд в отдельном потоке. , однако он находит, что callback является NullReference. Как я могу гарантировать, что обратный вызов не станет нулевым?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...