2012-08-18 4 views
-1

У меня есть этот код в .NET:Как контролировать выполнение в externl родной DLL

result = NativeMethods.gsapi_init_with_args(_ghostScriptInstance, args.Length, _argumentPointersHandle.AddrOfPinnedObject()); 

Это, в свою очередь, выполняет этот код

[DllImport("C:\\gsdll64.dll", EntryPoint = "gsapi_init_with_args")] 
public static extern int gsapi_init_with_args(IntPtr instance, int argc, IntPtr argv); 

Проблема заключается в том, что из-за пока неизвестно проблема в том, что собственное выполнение входит в бесконечный цикл и никогда не возвращается.

Вопрос в том, как я могу ограничить время выполнения этой оригинальной вещи. Могу ли я как-то сказать .NET, что если NativeMethods.gsapi_init_with_args не вернется в течение минуты, то убить собственное выполнение и вернуть?

+0

@ HansPassant Как это работает на SO, так это то, что если у вас нет ответа на вопрос, вы не можете его опубликовать. Я отметил ваш комментарий как не конструктивный/не по теме. – user1561202

+0

@ user1561202 Отметьте ваши комментарии как неконкретные. –

ответ

0

Возможно, вызовите метод в новом потоке и убейте поток, если вызов не завершится вовремя. Убивать поток плохо, но в этом конкретном случае я предполагаю, что у вас нет доступа к исходному коду встроенной функции.

Как-то Thread.Abort не работает (попытается выяснить, как работает потоковый поток), вместо создания управляемого потока вы можете создать собственный поток с помощью CreateThread и завершить его после таймаута.

[DllImport("Library.dll")] 
public static extern void InfiniteLoop(); 

[DllImport("kernel32")] 
private static extern int CreateThread(
    IntPtr lpThreadAttributes, 
    UInt32 dwStackSize, 
    IntPtr lpStartAddress, 
    IntPtr param, 
    UInt32 dwCreationFlags, 
    UInt32 lpThreadId 
); 

[DllImport("Kernel32.dll", CharSet = CharSet.Auto)] 
public static extern int TerminateThread(int hThread); 

[DllImport("Kernel32.dll", CharSet = CharSet.Auto)] 
public static extern int GetLastError(); 

private delegate int InvokeInfiniteLoop(IntPtr args); 

static void Main(string[] args) 
{ 
     InvokeInfiniteLoop invokeInfiniteLoop = (args1) => 
                { 
                 InfiniteLoop(); 
                 return 0; 
                }; 
    IntPtr infiniteLoopPtr = Marshal.GetFunctionPointerForDelegate(invokeInfiniteLoop); 
    int handle = CreateThread(IntPtr.Zero, 0, infiniteLoopPtr, IntPtr.Zero, 0, 0); 
    Thread.Sleep(TimeSpan.FromSeconds(5)); 
    int terminated = TerminateThread(handle); 
    Console.WriteLine(terminated); 
} 

Слово предостережения, прекращение нить опасно, вы можете прочитать об этом здесь: http://msdn.microsoft.com/en-us/library/windows/desktop/ms686717(v=vs.85).aspx. HansPassant прав, если источник доступен, вы можете его отладить и выяснить ошибку.

+0

Спасибо, но это не сработает. Обходное решение потока, которое вы предложили, позволяет мне выпускать и продолжать выполнение кода .NET, но внутренний код продолжает выполняться за кулисами. – user1561202

+0

Каким-то образом Thread.Abort не работает (попытается выяснить, как работает поток interop threading), вместо создания управляемого потока вы можете создать собственный поток с помощью CreateThread и завершить его после таймаута. Я обновил ответ с помощью источника. –

+0

После того, как дальнейшие исследования выглядят (как я подозревал с самого начала), что это обходное решение совершенно неверно. Создание и завершение неуправляемого кода приведет к утечке стека. Мне нужно будет создать отдельный исполняемый файл, который будет завершен Process.Kill(); – user1561202

Смежные вопросы