2017-12-21 7 views
0

私はC#アプリケーションを持っています。使用されるStackコレクションがあります。私は、TryPopからConcurrentStackに対して値を取得することを保証しますか

今、このコレクションは多くのスレッドからアクセスされているため、スレッドセーフにする必要があります。

ですから、私はConcurrentStack Collectionを代わりに使用したいと考えています。

これはTryPeek、TryPop、TryPushを使用し、成功/失敗を示すTrue/Falseフラグを返します。

このフラグは、オブジェクトがコレクション内に存在するかどうかを認識していますか?それとも、別のスレッドがコレクションに同時にアクセスしていて、アクションを再試行する必要があるために失敗する可能性があります。この方法は、falseアイテムを除去することができない場合/返却、又はTryPopCore戻りfalseを返し

public bool TryPop(out T result) 
{ 
    ConcurrentStack<T>.Node head = this.m_head; 
    if (head == null) 
    { 
     result = default(T); 
     return false; 
    } 
    if (Interlocked.CompareExchange<ConcurrentStack<T>.Node>(ref this.m_head, head.m_next, head) == head) 
    { 
     result = head.m_value; 
     return true; 
    } 
    return this.TryPopCore(out result); 
} 

:ここ

+2

ドキュメントには、コレクションに削除して返すアイテムがない場合に 'false'が返されると記載されています。 – Amy

+0

その確認のために@amyありがとうございました –

+0

私はあなたがここで尋ねようとしているものが不明です。しかし、不確かな場合に備えて、これはマルチスレッド化されたアクセスだとすでに述べています。戻り値について何らかの*推論を行う*合理的*は、次回コレクションにアクセスしようとするときの状態に無関係*です。 –

答えて

2

ConcurrentStack.TryPop<T>()のソースコード(ILSpyによって逆コンパイルされるように)です。

private bool TryPopCore(out T result) 
{ 
    ConcurrentStack<T>.Node node; 
    if (this.TryPopCore(1, out node) == 1) 
    { 
     result = node.m_value; 
     return true; 
    } 
    result = default(T); 
    return false; 
} 

だからTryPopCore(int, out ConcurrentStack<T>.Node)が成功したかどうかを返す:だからここにいることである

private int TryPopCore(int count, out ConcurrentStack<T>.Node poppedHead) 
{ 
    SpinWait spinWait = default(SpinWait); 
    int num = 1; 
    Random random = new Random(Environment.TickCount & 2147483647); 
    ConcurrentStack<T>.Node head; 
    int num2; 
    while (true) 
    { 
     head = this.m_head; 
     if (head == null) 
     { 
      break; 
     } 
     ConcurrentStack<T>.Node node = head; 
     num2 = 1; 
     while (num2 < count && node.m_next != null) 
     { 
      node = node.m_next; 
      num2++; 
     } 
     if (Interlocked.CompareExchange<ConcurrentStack<T>.Node>(ref this.m_head, node.m_next, head) == head) 
     { 
      goto Block_5; 
     } 
     for (int i = 0; i < num; i++) 
     { 
      spinWait.SpinOnce(); 
     } 
     num = (spinWait.NextSpinWillYield ? random.Next(1, 8) : (num * 2)); 
    } 
    if (count == 1 && CDSCollectionETWBCLProvider.Log.IsEnabled()) 
    { 
     CDSCollectionETWBCLProvider.Log.ConcurrentStack_FastPopFailed(spinWait.Count); 
    } 
    poppedHead = null; 
    return 0; 
    Block_5: 
    if (count == 1 && CDSCollectionETWBCLProvider.Log.IsEnabled()) 
    { 
     CDSCollectionETWBCLProvider.Log.ConcurrentStack_FastPopFailed(spinWait.Count); 
    } 
    poppedHead = head; 
    return num2; 
} 

あなたが見ることができるように、それは項目を削除し、それを返すことができない場合にはfalseを返します。この最後の関数には多くのことがあります。逆コンパイルされたコードは最もクリーンではありませんが、ドキュメントの内容に準拠しているようです。

+0

ありがとうございます。私は今仕事から急いでいて、戻ってくるときにこれを見るでしょう。再度、感謝します。 –

関連する問題