1

SerialPort.NET を使用した同期通信 (シリアル経由) と、.NETを使用した非同期通信 (イーサネット経由)の両方を実行しようとしていますSocket

SerialPort現在の実装には、との両方を宣言する Connection クラスがSocketあり、ユーザーが GUI で定義したデバイスの接続タイプ (COM またはイーサネット) に応じて、Connection クラスは適切なシリアル ポートまたはソケット ポートを初期化します。

すべての接続を保持する ConnectionManager があります。したがって、ユーザーが同じ接続情報を使用してデバイスを作成しても、新しい接続は作成されません。代わりに、ConnectionManager にある Connection が割り当てられるだけです。

同期通信と非同期通信を行う必要があるため、これは問題です。何が起こるかというTaskと、デバイスに接続しているときに s を作成するループがあり、それぞれTaskが and を実行しようとしていSendますReceive。ソフトウェアがタスクを作成するよりも、デバイスがタスクを完了するのに時間がかかるため、そこに多くの並行性の問題 (ブロックされたスレッド) です。同期通信を行う必要があるためMutex、送信前に a をロックし、送信Send後にミューテックスを解放して、Receiveすべての送信で確実に受信できるようにします。これは良くありません。なぜなら、非同期通信を行おうとすると、ミューテックスが原因で通信が制限されるからです。

私の質問は、非同期通信と同期通信を同時に処理しようとする場合に従うべき最良の設計は何ですか? Send、Receive、Open、Close メソッドを持つ Connection インターフェイスを継承する 2 つの異なる接続クラス (AConnection、BConnection) が必要ですか?

どんな助けでも大歓迎です。

4

1 に答える 1

3

一般に、クラスの継承よりもオブジェクトコンポジションを常に優先する必要があります。WorkClassつまり、必要な機能のほとんどを備えたスーパークラス(say )を作成し、それを継承してそれらの関数を使用/オーバーライドする2つの具象サブクラス(say AWorkClass : WorkClassand BWorkClass : WorkClass)を作成する代わりに、2つの具体的な折り目を付ける必要があります。メンバー変数として「a」を持つ継承(AClassおよび)のないクラス。BClassWorkClass

これをもう少し進めて、ultimatleyがあなたの質問に答えようとしているので、 「戦略」(同期通信と非同期通信の間など)を非常に簡単に切り替えて、新しい「戦略」は、多くの労力をかけずに(または波及効果をそれほど心配することなく既存の戦略に変更を加えることで)実行されます。

C#で実装された戦略の例を次に示します。

namespace Your.App
{
//correct implementation of the Strategy Pattern
    interface ICommunication
    {
        void Send();
    }
    class SyncCommunication : ICommunication
    {
        public void Send() { /*your sync code*/ }
    }
    class AsyncCommunication : ICommunication
    {
        public void Send() { /*your async code*/ }
    }
    public class WorkClass
    {
        ICommunication Strategy { get; set; }
        public WorkClass()
        {
            UseAsync = false;
        }
        bool _useAsync;
        public bool UseAsync 
        {
            get { return _useAsync; }
            set
            {
                _useAsync = value;
                if(_useAsync)
                    Strategy = new AsyncCommunication();
                else
                    Strategy = new SyncCommunication ();
            }
        }
        public void Send()
        {
            Strategy.Send();
        }
    }
}

これを最初の段落と結び付けるには、次のようにWorkClassを使用します。

namespace Your.App
{
//correct implementation of the Strategy Pattern
    public class MyWorkContext
    {
        WorkClass Worker {get; set;}
        public MyWorkContext()
        {
            Worker = new WorkClass();
        }

        public void SendMyData()
        {
            if(someConditionIsMet)
                Worker.UseAsync = true;
            else
                Worker.UseAsync = false;
            Worker.Send();
        }
    }
}

あなたのユーザーWorkClassMyWorkContextこの場合)はあなたの戦略について何も知らず、またそうすべきではないことがわかります。それは、それが何をすべきかを知るのに十分なだけ労働者に伝え、そして労働者はそれをするためにどの戦略を使う必要があるかを知っています。戦略自体は、作業が実際にどのように行われるかを知っている唯一のものであり、テストとメンテナンスに非常に役立ちます。

于 2012-09-20T23:58:37.203 に答える