マルチスレッドNI-488.2アプリケーションの補助コール

NI-488.2

マルチスレッドNI-488.2アプリケーションの補助コール

マルチスレッドNI-488.2アプリケーションで、すべてのNI-488.2コールを1つのスレッドから行う場合、NI-488.2グローバル関数IbstaIberrIbcnt)を引き続き問題なく使用できます。NI-488.2グローバル関数は、プロセス単位で定義されており、各プロセスはそれぞれのNI-488.2グローバル関数のコピーにアクセスします。

マルチスレッドNI-488.2アプリケーションで、NI-488.2コールを複数のスレッドから行う場合は、何らかの形式の同期(セマフォなど)なしでは、NI-488.2グローバル関数を問題なく使用することができなくなります。次に、例を使ってその理由を示します。

あるプロセスに、NI-488.2コールを行う2つの別々のスレッド(スレッド1とスレッド2)があるとします。スレッド1がNI-488.2グローバル関数の1つを調べようとしている状態で、スレッド1はプリエンプトされ、スレッド2が実行できる状態になるとします。スレッド2は、NI-488.2コールの実行を続け、NI-488.2グローバル関数は自動的に更新されます。後でスレッド1の実行が許可されたときには、調べようとしていたNI-488.2グローバル変数は更新されているので、その値には信頼性がなくなります。

この例は、よく知られているマルチスレッドに関する問題を示しています。複数の実行スレッドから、プロセスのグローバル関数にアクセスすることは安全ではありません。この問題は、次の2通りの方法で回避することができます。

同期を取り、プロセスグローバル関数へのアクセスを保護します。

プロセスグローバル関数を使用しません。

同期による解決方法を実装する場合は、NI-488.2コールを呼び出し、NI-488.2コールで変更されたNI-488.2グローバル関数を参照するコードが同期プリミティブで保護されていることを確認してください。たとえば、各スレッドがNI-488.2コールを実行する前にセマフォを取得し、コールによって変更されたNI-488.2グローバル関数を参照した後にセマフォを解放します。同期プリミティブの使用方法に関しては、ご使用の開発環境に付属のWindows同期オブジェクトの使用方法に関するドキュメントを参照してください。

プロセスグローバル関数を使わない場合は、NI-488.2コールの専用セットを使ってNI-488.2グローバル関数のスレッド単位のコピーにアクセスすることができます。スレッドがNI-488.2コールを実行する際に、ドライバはそのスレッド用のNI-488.2グローバル関数のコピーを保持します。ドライバは、各スレッド用に別々のコピーを保持します。次のコードは、これらのスレッド単位のNI-488.2グローバル関数にアクセスするために使用するコールを示すものです。

unsigned long ThreadIbsta(); // スレッド特定のIbsta()を返す

unsigned long ThreadIberr(); // スレッド特定のIberr()を返す

unsigned long ThreadIbcnt(); // スレッド特定のIbcnt()を返す

アプリケーションでは、プロセス単位のNI-488.2グローバル関数にアクセスする代わりに、スレッド単位のNI-488.2グローバル関数を取得するためのコールを使用してください。以下に例を示します。

if (Ibsta() & ERR)

の代わりに次のコードを使います。

if (ThreadIbsta() & ERR)

メモ ibnotifyをアプリケーションで使う場合は、NI-488.2ドライバによって作成された別のスレッドでibnotifyコールバックが実行されます。このため、アプリケーションがibnotifyコールバック関数からNI-488.2コールを行い、別の場所からもNI-488.2コールを行う場合は、プロセス単位のNI-488.2グローバル関数ではなく、ThreadIbstaThreadIberrThreadIbcntでスレッド単位のNI-488.2グローバル関数を使う必要があります。