Нарушение прав доступа с неуправляемой DLL - PullRequest
1 голос
/ 02 сентября 2010

В настоящее время мы используем неуправляемую DLL от поставщика, которая позволяет нам получить доступ к определенному инструменту. Конкретная интересующая функция указана в заголовочном файле следующим образом:

extern "C" short CCONV acq_get_board_count ();

В моем приложении у меня есть оператор pinvoke:

public class bograms
{
    [DllImport("bograms.dll", EntryPoint = "acq_get_board_count", CallingConvention = CallingConvention.StdCall)]
    public static extern short acq_get_board_count();
}

Теперь в моем коде я пытаюсь справиться с избыточностью, поэтому я создаю таймер, который пытается поддерживать работу:

public class Instrument
{
    private System.Threading.Timer keepAliveTimer;
    public Instrument()
    {
        keepAliveTimer = new Timer(new TimerCallback(this.KeepAlive), null, 0, 300000);
    }

    void KeepAlive(object state)
    {
        if(instrumentIsUninitialized) // some check that accomplishes this
        {
            Console.WriteLine("Some status statements"); // in console
            short numBoards = bograms.acq_get_board_count();
            Console.WriteLine("Initialization caught {0} boards.", numBoards); // not in console
        }
    }
}

Первый тик таймера, он получает ноль плат (предположительно потому, что оборудование не завершило инициализацию) и выводит оба сообщения на консоль. Тем не менее, во втором тике я получаю ошибку APPCRASH 0xc0000005 в bograms.dll, которую я считаю ошибкой нарушения прав доступа. Установка try / catch вокруг вызова не улавливает ошибку. Первая строка находится в консоли, вторая строка - нет. При отладке файла дампа (насколько мне известно, ноу-хау) ошибка возникает при этом вызове.

Не верно ли мое утверждение pinvoke? Это такая простая функция, что я не могу поверить, что это будет, но я что-то упустил? Поток из-за таймера вызывает какие-то проблемы?

Я предполагаю, что первый вызов переводит его в некое состояние, которое приводит к сбою второго вызова, особенно если учесть, что аппаратная инициализация происходит за кулисами. Если это так, есть ли способ выгрузить драйвер DLL, чтобы он мог вернуться в исходное состояние, в котором он должен быть?

Или есть еще какие-то вещи, о которых вы можете подумать?

1 Ответ

2 голосов
/ 02 сентября 2010

Одна вещь, которая сразу приходит на ум, - можно ли безопасно использовать API в разных потоках. Обратные вызовы System.Threading.Timer входят в поток ThreadPool, поэтому каждый раз он может быть другим. Некоторые API имеют требования к соприкосновению потоков, что означает, что они могут быть вызваны только из одного потока. Вместо этого все еще может быть некоторая проблема параллелизма, если два вызова одного и того же API происходят одновременно. В конце концов вы можете обнаружить, что проблема не связана с многопоточностью. Я просто пытаюсь представить одно возможное объяснение.

...