0

管理アプリケーションを作成しました。私のアプリケーションが行うことの 1 つは、指紋リーダーがプラグインまたはプラグアウトされるたびに検出できるプラグインに登録することです。クラスは次のようにイベントをサブスクライブします。

//Subscribe to the plug, unplug and imageAcquired events from the GrFingerXCtrlClass library.
FingerXCtrlClass.SensorPlug += ReaderPlug;
FingerXCtrlClass.SensorUnplug += ReaderUnplug;
FingerXCtrlClass.ImageAcquired += ImageAcquired;

最初にプログラムに積極的に取り組んでいたとき、私は WPF アプリケーションを開発しました。このアプリケーションを通じて、いくつかのリストを表示し、いくつかの設定を切り替えることができたので、サービスがうまく機能していると確信しています. この WPF アプリケーションでは、サービスをインスタンス化して作成しました。

ProjectServiceLogic logic = new ProjectServiceLogic();

これで、インストーラーが作成されました。したがって、アプリケーションを初期化する ProjectService クラスがありました。これは次のように行われています。

protected override void OnStart(string[] args)
{
    log.Debug("Starting service...");
    _worker = new Thread(new ThreadStart(StartService));
    _worker.IsBackground = true;
    _worker.Name = "ServiceThread";
    _worker.SetApartmentState(ApartmentState.STA);
    _worker.Start();
    log.Debug("Successfully started service");
}

void StartService()
{
    serviceLogic = new ProjectServiceLogic();
    while (!_shutdownEvent.WaitOne(0))
    {

    }
}

プログラムがインストールされ、サービスが開始されます。サービスをデバッグしていると、サブスクライブ コードが実行されることに気付きました。ただし、デバイスをプラグインしてもイベントはトリガーされませんが、WPF アプリケーションを介してローカルで実行し、サービス ロジックをインスタンス化するとトリガーされます。なぜ今はうまくいかないのですか?

4

1 に答える 1

1
_worker.SetApartmentState(ApartmentState.STA);

シングル スレッド アパートメントを選択するには、STA スレッドのコントラクトを実装する必要があります。基本的な要件は 2 つだけです。スレッドをブロックすることはできず、メッセージ ループをポンピングする必要があります。メッセージ ループは、COM オブジェクトのメソッド呼び出しが常にオブジェクトを作成したスレッドから行われることを COM が保証できるようにするために不可欠です。これにより、スレッド セーフが保証されます。また、Control.BeginInvoke と Dispatcher.BeginInvoke を機能させる .NET のメカニズム。

COM コンポーネントは、その保証が整っていることを期待しており、多くの場合、独自のスレッド間マーシャリングを処理するためにメッセージ ディスパッチャに依存しています。Dispatcher.BeginInvoke のように。

必要に応じて実際にメッセージ ループをポンピングしないと、2 つの問題が発生します。まず第一に、予想通り、ワーカー スレッドからオブジェクトを呼び出すとデッドロックが発生します。COM は PostMessage を使用して、STA スレッドに呼び出しをディスパッチするように依頼します。しかし、スレッドがメッセージ キューからメッセージを取得していない場合、それは起こりません。2 つ目の問題は、ここで発生している可能性が高いことです。コンポーネント自体が PostMessage を使用して、STA スレッドでイベントを発生させます。イベントが発生しない障害モード。また、古典的に WebBrowser が誤動作する方法では、DocumentCompleted イベントを取得することはありません。

メッセージ ループ Application.Run() をポンピングする必要があります。Winforms またはその WPF バージョンのいずれかで実行できます。選択してください。Winforms の例はこちら

于 2013-05-08T11:19:23.700 に答える