現在、Thread.Interrupt が P/Invoke またはネイティブ呼び出しとどのように連携するかを調査しています。MSDN で、ネイティブ呼び出しにあるスレッドを中止 (Thread.Abort) できないことを読みました (他のユース ケースも適用される可能性があります)。しかし、WaitSleepJoin 状態にあるネイティブ スレッドについて同じことを述べているリファレンスは見つかりませんでした。
この質問は、Abort または Interrupt を呼び出す必要があるかどうかに関するものではなく、これに関する信頼できるドキュメントをどこで見つけることができるかに関するものです。このための G-ing は、有用な出力を提供しませんでした。
私のテスト例:
#ifdef NATIVEFUNCTIONS_EXPORTS
#define NATIVEFUNCTIONS_API __declspec(dllexport)
#else
#define NATIVEFUNCTIONS_API __declspec(dllimport)
#endif
#include <iostream>
extern "C"
{
NATIVEFUNCTIONS_API void EndlessWait(char const* mutexName)
{
std::cout << "entering the endless wait." << std::endl;
HANDLE mutex = CreateMutex(NULL, FALSE, mutexName);
WaitForSingleObject(mutex, INFINITE);
std::cout << "leaving the endless wait." << std::endl;
}
};
無限にミューテックスを待機する関数をエクスポートするネイティブ C++-DLL。
次に、待機をキャンセルしようとする C# .NET の対応物:
using System;
using System.Threading;
using System.Runtime.InteropServices;
namespace InterruptingNativeWaitingThread
{
class Program
{
[DllImport("NativeFunctions.dll", CharSet=CharSet.Ansi)]
static extern void EndlessWait(string str);
static void Main(string[] args)
{
string mutexName = "interprocess_mutex";
Mutex m = new Mutex(false, mutexName);
m.WaitOne();
Thread t = new Thread(() => { EndlessWait(mutexName); });
t.Start();
Thread.Sleep(1000);
t.Abort();
if(!t.Join(5000))
Console.WriteLine("Unable to terminate native thread.");
t.Interrupt();
if(!t.Join(5000))
Console.WriteLine("Unable to interrupt the native wait.");
Console.WriteLine("Release the mutex.");
m.ReleaseMutex();
t.Join();
}
}
}
このアプリを実行すると、次の出力が生成されます。
entering the endless wait.
Unable to terminate native thread.
Unable to interrupt the native wait.
Release the mutex.
leaving the endless wait.
このコンテキストでは Abort は期待どおりに機能しませんが、msdn は割り込みについて何も言いません。一方ではうまくいくと思います.Wait状態にあるマネージスレッドは、ネイティブのWaitForSingleObjectまたはWaitForMultipleObjectsも呼び出すためです。一方で、割り込まれるネイティブスレッドがすべての例外を期待することをサポートしていない可能性があります。
どんなドクターでも大歓迎です!
どうもありがとう、
オバネス
PS私はMSDNで、中止されるスレッドがアンマネージコードから戻るまで待機し、スレッドがWaitSleepJoin状態にある場合は最初に割り込みを呼び出し、それを中止することも発見しました。ただし、割り込みがネイティブの WaitSleepJoin に割り込みできないという意味ではありません。