3

みなさん、こんにちは。

私は、現在の作業プロジェクトでどのマルチスレッドアプローチを利用するかを理解するのに非常に時間がかかっています。私は人生でマルチスレッドアプリを書いたことがないので、これはすべて混乱し、非常に圧倒されます。これ以上の苦労なしに、これが私の背景の話です:

私は、会社のR&Dラボでテスト機器の制御アプリケーションの作業を引き継ぐように割り当てられました。プログラムは、3つの異なるデバイスとのシリアル通信を半同時で送受信できる必要があります。元のプログラムはVB6(マルチスレッドなし)で作成されており、テスト中に過剰なシリアル通信が原因でUIがロックされたときに安全上の問題が発生するまで、テストが必要な新しい製品で動作するようにモッディングする予定でした。 。その結果、テスターハードウェアの一部が爆発したため、最初はより快適で、マルチスレッドがこの問題の解決に役立つと考えたため、VB.Netでアプリを書き直してみることにしました。

私の計画は、メインのアプリスレッドから他の機器にコマンドを送信し、タイミングが重要なときにメインスレッドがロックされないように、受信側を独自のスレッドにスピンオフすることでした。しかし、私はまだ自分の選択肢に同意していません。問題を追加するには、受信した通信を受信時に個別のリッチテキストボックスに表示する必要がありますが、特定のデバイスからのデータをメインプログラムで解析する必要がありますが、最新のテストの結果のテキストのみです。 (ただし、受信したすべてのデータを含めるにはテキストボックスが必要です)。

これまで、デリゲートを調査し、スレッドを自分で処理して、BackgroundWorkersの調査を開始しました。今日、デリゲートを使用しようとしましたが、テキストボックスを更新する方法がわかりませんでした。デリゲート関数自体では実行できないため、これを実行するにはコールバック関数を使用する必要がありますか?スレッドを自分で処理する際に私が目にする問題は、スレッドとプログラムの残りの部分との間でデータをやり取りする方法を理解することです。BackgroundWorkers、私が言ったように、私は調査を始めたばかりなので、彼らについてどう考えるかはまだわかりません。

また、何らかの理由で停止がトリガーされるまで、生成されたスレッドを継続的に実行する計画であったことにも注意する必要があります。上記のオプションのいずれかでこれは可能ですか?私がまだ発見していない他のオプションはありますか?

情報の長さとバラバラな情報をぶらぶらしているように見えるという事実については申し訳ありませんが、私は厳しい締め切りにあり、まっすぐに考えることができないほどストレスを感じています!アドバイス/情報/リンクは大歓迎です。方向を選んで前に進むことができるように、オプションの計量に助けが必要です。この混乱を読むために時間を割いてくれたみんなに感謝します!

4

1 に答える 1

4

OK、シリアルポート、スレッド間通信、RichTextBoxなどのGUIコンポーネントでの表示は、プロトコルをデコードしてステートマシンに起動するために、着信データをすばやく解析する必要があります。

3つのシリアルポートすべてが同じ「processControl」ステートマシンで起動しますか?

もしそうなら、おそらくイベント/データオブジェクトをアセンブルし、それらを1つのスレッドによって実行されるステートマシンにキューイングすることによってこれを行う必要があります(BlockingCollectionを参照)。これは、状態エンジンをミューテックスでロックするよりもはるかに安全で、理解/デバッグが容易なようなものです。

'comms'クラスを定義して、データを保持し、システム内で持ち運びます。列挙型をオンにすることで、列挙型を取得するスレッドが正しいことを実行できるように、「コマンド」列挙型が必要です。状態エンジンで使用されるものに設定できる「イベント」メンバー。「boolloadChar(char inChar)」は、charごとのデータをスローでき、完全な検証済みプロトコルユニットがアセンブルされ、チェックされ、データマンバーに解析された場合にのみ「true」を返します。含まれているデータに関する情報をテキスト形式でダンプする「stringtextify()」メソッド。テキストを保持するための一般的な「ステータス」文字列。'errorMess'文字列と例外メンバー。

あなたはおそらくその考えを理解するでしょう-この通信クラスはシステムの周りで何でも転送することができます。スレッドが他の通信インスタンスを参照せずにデータとメソッドを使用できるようにカプセル化されています。ロックは必要ありません。ブロッキングコレクションのスレッドを処理するためにキューに入れ、GUIスレッドにBeginInvokedしてコンテンツを表示することができます。

serialPortオブジェクトで、起動時に通信を作成し、serialPortインスタンスを使用してメンバーをロードします。また、DataReceivedイベントが発生すると、一度に1文字ずつargsからデータを取得し、comms.loadChar()を起動します。loadChar呼び出しがtrueを返した場合、commsインスタンスをステートマシン入力BlockingCollectionのキューに入れ、すぐに別の通信を作成して、新しい通信にデータのロードを開始します。それを永遠に続けてください-検証されたプロトコルユニットが得られるまで通信インスタンスにcharをロードし、ステートマシンにキューイングします。各シリアルポートには独自のプロトコルがある可能性があります-OK、したがって、独自のプロトコルを正しくデコードするには、loadCharをオーバーライドする3つの通信子孫が必要になる場合があります。

ステートマシンスレッドでは、入力からcommsオブジェクトを取得し、commsオブジェクトからの現在の状態とイベントを使用して状態エンジンの処理を実行します。SMアクションルーチンが何かを表示することを決定した場合、コマンドを「displaySomeStuff」に設定して、GUIスレッドへの通信をBeginInvokeします。GUIスレッドが通信を取得すると、コマンドの大文字と小文字を切り替えて、何を表示するかなどを決定できます。

とにかく、それが私のすべてのプロセス制御タイプのアプリを構築する方法です。データは「comms」オブジェクトインスタンスでシステム内を流れます。commsオブジェクトが一度に複数のtheadによって操作されることはありません。これはすべて、BlockingCollection(または同様の)、キュー、またはGUIスレッドに移動する場合はBeginInvoke()のいずれかでメッセージを渡すことによって行われます。

唯一のロックはキューにあるため、カプセル化されます。明示的なロックはまったくありません。これは、明示的なデッドロックがまったく発生しないことを意味します。頭痛はしますが、ロックアップはありません。

ああ-'Thread.Join()'に近づかないでください。

于 2012-04-25T23:29:45.340 に答える