0

私がやろうとしているのは、一度にいくつかの異なる Tcp ポートをリッスンし、メッセージを任意のオブザーバーにパイプする「リスナー」を作成することです。

疑似コード:

private bool _Listen = false;
public void Start()
{
    _Listen = true;
    Task.Factory.StartNew(() => Listen(1);
    Task.Factory.StartNew(() => Listen(2);
}

public void Stop()
{
    _Listen = false;
}

private async void Listen(int port)
{
     var tcp = new TcpClient();
     while(_Listen)
     {
          await tcp.ConnectAsync(ip, port);
          using (/*networkStream, BinaryReader, etc*/)
          {
               while(_Listen)
               {
                   //Read from binary reader and OnNext to IObservable
               }
          }
     }
}

(簡潔にするために、2 つの while 内の try/catch を省略しました。どちらもフラグをチェックします)

私の質問は次のとおりです。フラグをロックする必要がありますか?もしそうなら、それは非同期/待機ビットとどのように結び付けられますか?

4

4 に答える 4

1

フラグをロックする必要がありますか?もしそうなら、それは非同期/待機ビットとどのように結び付けられますか?

何らかの方法でフラグへのアクセスを同期する必要があります。そうしないと、コンパイラは次の最適化を行うことができます。

bool compilerGeneratedLocal = _Listen;
while (compilerGeneratedLocal)
{
    // body of the loop
}

これはあなたのコードを間違ったものにするでしょう。

それを修正する方法のいくつかのオプション:

  1. boolフラグをマークしvolatileます。これにより、フラグの現在の値が常に読み取られるようになります。
  2. 使用しますCancellationToken(Panagiotis Kanavos の提案による)。これにより、基になるフラグがスレッドセーフな方法でアクセスされるようになります。また、多くの非同期メソッドが をサポートCancellationTokenしているため、それらをキャンセルできるという利点もあります。
于 2013-08-23T13:13:26.087 に答える
1

複数のスレッドを処理する可能性がある場合は、何らかの形式のイベント ( などManualResetEventSlim) がより明白な選択になります。

private ManualResetEventSlim _Listen;
public void Start()
{
    _Listen = new ManualResetEventSlim(true);
    Task.Factory.StartNew(() => Listen(1);
    Task.Factory.StartNew(() => Listen(2);
}

public void Stop()
{
    _Listen.Reset();
}

private async void Listen(int port)
{
     var tcp = new TcpClient();
     while(_Listen.IsSet)
     {
于 2013-08-23T07:15:26.270 に答える