4

CommunicatorTCP ポートでデータを受信するバックグラウンド スレッドで動作するクラスがあります。

Communicator にはOnDataReceivedEventHandler<DataReceivedEventArgs>タイプのイベントがあります。

Consumerイベントにサブスクライブされたメソッドを含む別のクラスがありCommunicator.OnDataReceivedます。

comm.OnDataReceived += consumer.PresentData;

クラスは Form コンストラクター内で作成され、Consumerそのメソッドの 1 つが別のスレッドで呼び出されます。このメソッドは無限ループなので、アプリケーションの実行中はそのメソッドにとどまります。

私がやりたいのは、イベントが消費者のスレッドCommunicator.OnDataReceivedでメソッドを呼び出すことです。consumer.PresentData

それはほぼ可能ですか?そうである場合、どのようなメカニズム (同期クラス) を使用する必要がありますか?

4

4 に答える 4

4

これをコードのどこかに追加します。

public static void Invoke(ISynchronizeInvoke sync, Action action) {
    if (!sync.InvokeRequired) {
        action();
    }
    else {
        object[] args = new object[] { };
        sync.Invoke(action, args);
    }
}

次に、OnDataReceived 内で、次のことができます。

Invoke(consumer, () => consumer.PresentData());

これにより、「consumer」で「consumer.PresentData」が呼び出されます。

設計上の問題 (消費者がコミュニケーターを参照する) については、次のようなコミュニケーター内にメソッドを導入できます。

class Communicator {
    private ISynchronizeInvoke sync;
    private Action syncAction;

    public void SetSync(ISynchronizeInvoke sync, Action action) {
        this.sync = sync;
        this.syncAction = action;
    }

    protected virtual void OnDataReceived(...) {
        if (!sync.InvokeRequired) {
            syncAction();
        }
        else {
            object[] args = new object[] { };
            sync.Invoke(action, args);
        }
    }
}

これにより、コンシューマ クラスから ISynchronizedInvoke を渡すことができます。したがって、コンシューマー アセンブリで ISynchronizedInvoke を作成することになります。

class Consumer {
    public void Foo() {
        communicator.SetSync(this, () => this.PresentData());
    }
}

したがって、基本的には、呼び出しを行うために必要なものをすべて作成し、それをコミュニケーターに渡すだけです。これにより、コミュニケーターでインスタンスまたはコンシューマーへの参照が必要になることが解決されます。

また、私はこれをテストしていないことに注意してください。これはすべて理論的に行っていますが、うまく機能するはずです。

于 2011-07-07T19:34:15.210 に答える
1

それは可能であるはずです。実行用のキューを作成するか、Dispatcherオブジェクトを確認することができます。これは、いくつかのメソッドをUIスレッドにプッシュするのに役立ちます(場合によっては唯一の方法として必須です)。

于 2011-07-07T19:30:57.757 に答える
1

メソッドの実行を開始スレッドからターゲット スレッドに転送するマーシャリング操作をターゲット スレッドが受け入れるように設計されている場合にのみ、スレッドで実行するメソッドを取得できます。

これを機能させる 1 つの方法は、Consumerクラスに を実装させることISynchronizeInvokeです。次に、クラスがマーシャリング操作を実行するために使用できるインスタンスをCommunicator受け入れるようにします。例としてクラスをISynchronizeInvoke見てみましょう。には、またはを呼び出して、同期オブジェクトをホストするスレッドにイベントをマーシャリングするために使用できるプロパティがあります。System.Timers.TimerSystem.Timers.TimerSynchronizingObjectElapsedISynchronizeInvoke.InvokeISynchronizeInvoke.BeginInvoke

ISynchronizeInvoke注意が必要なのは、Consumerクラスにどのように実装するかです。そのクラスによって開始されたワーカー スレッドは、デリゲートを処理できるようにプロデューサー/コンシューマー パターンを実装する必要があります。クラスはこれBlockingCollectionを比較的簡単にしますが、それでもかなりの学習曲線があります. 試してみて、さらにサポートが必要な場合は、より焦点を絞った質問を投稿してください。

于 2011-07-07T19:35:25.220 に答える
1

BackgroundWorkerクラスを使用してみてください。

于 2011-07-07T19:27:52.887 に答える