none
Generic.List(of T)のスレッドセーフな使い方 RRS feed

  • 質問

  • こんにちは。いつもお世話になっております。

    VB2008.NETでWindowsフォームアプリケーションを作成しています。

    List(of T)を用いて配列を作成したいのですが

    書込みと読出しを別なスレッド同士で行うと問題が出たと思います。

    そこで、同期をとる手段としてQueueクラスは以下のようにして

    しておりますが、Listも同様な方法でインターロックをかけることが

    できるのでしょうか?

    以上、ご教示よろしくお願いします。

        Public Function In_FIFO(ByVal x As ELEM) As Integer
    
            Dim intRet As Integer = 0
    
            SyncLock mobjLock
    
                mQueue.Enqueue(x)
    
            End SyncLock
    
            Return intRet
    
        End Function
    

    2016年11月21日 7:50

回答

  • 提示のコードだと、戻り値が無意味なのでは(常に 0 を Return している)


    > List(of T)を用いて配列を作成したいのですが

    ここでいう配列というのは、コレクションの事でしょうか。
    それとも、ToArray メソッドで変換することを指していますか?


    > Listも同様な方法でインターロックをかけることが

    List(Of ) を利用する際に、その都度
     SyncLock DirectCast(lst, ICollection).SyncRoot
    などとして Lock することはできます。
    別途 ReaderWriterLockSlim を用意しても良いですけれどね。


    また、.NET 3.0 の System.ServiceModel を参照設定することで、スレッドセーフなコレクションである SynchronizedCollection(Of ) クラスを、List(Of ) の代替として利用することもできます。

    といっても、メンバー(Add、Contains、Clear、Count など)のそれぞれがスレッドセーフというだけなので、複合的な操作、たとえば
     If syncCollection.Count > 0 Then
      Return syncCollection(0) '既に削除されているかも…
     End If
    あるいは For Each などといったケースでは保護されません。

    複合処理を必要とする場合は、List(Of ) と同様に、コレクションを呼び出す側にて追加の対処が必要です。たとえば SyncLock syncCollection.SyncRoot など。
    2016年11月21日 8:48

すべての返信

  • 提示のコードだと、戻り値が無意味なのでは(常に 0 を Return している)


    > List(of T)を用いて配列を作成したいのですが

    ここでいう配列というのは、コレクションの事でしょうか。
    それとも、ToArray メソッドで変換することを指していますか?


    > Listも同様な方法でインターロックをかけることが

    List(Of ) を利用する際に、その都度
     SyncLock DirectCast(lst, ICollection).SyncRoot
    などとして Lock することはできます。
    別途 ReaderWriterLockSlim を用意しても良いですけれどね。


    また、.NET 3.0 の System.ServiceModel を参照設定することで、スレッドセーフなコレクションである SynchronizedCollection(Of ) クラスを、List(Of ) の代替として利用することもできます。

    といっても、メンバー(Add、Contains、Clear、Count など)のそれぞれがスレッドセーフというだけなので、複合的な操作、たとえば
     If syncCollection.Count > 0 Then
      Return syncCollection(0) '既に削除されているかも…
     End If
    あるいは For Each などといったケースでは保護されません。

    複合処理を必要とする場合は、List(Of ) と同様に、コレクションを呼び出す側にて追加の対処が必要です。たとえば SyncLock syncCollection.SyncRoot など。
    2016年11月21日 8:48
  • 提示のコードだと、戻り値が無意味なのでは(常に 0 を Return している)

     >>そうです。借りたコードなので見ていませんでした

    > List(of T)を用いて配列を作成したいのですが

    ここでいう配列というのは、コレクションの事でしょうか。
    それとも、ToArray メソッドで変換することを指していますか?

     >>コレクションのことでした。

    > Listも同様な方法でインターロックをかけることが

    List(Of ) を利用する際に、その都度
     SyncLock DirectCast(lst, ICollection).SyncRoot
    などとして Lock することはできます。
    別途 ReaderWriterLockSlim を用意しても良いですけれどね。


    また、.NET 3.0 の System.ServiceModel を参照設定することで、スレッドセーフなコレクションである SynchronizedCollection(Of ) クラスを、List(Of ) の代替として利用することもできます。

    といっても、メンバー(Add、Contains、Clear、Count など)のそれぞれがスレッドセーフというだけなので、複合的な操作、たとえば
     If syncCollection.Count > 0 Then
      Return syncCollection(0) '既に削除されているかも…
     End If
    あるいは For Each などといったケースでは保護されません。

    複合処理を必要とする場合は、List(Of ) と同様に、コレクションを呼び出す側にて追加の対処が必要です。たとえば SyncLock syncCollection.SyncRoot など。

    >>勉強不足すぎで、申し訳ありません。

    もう少し勉強して質問させて頂きます。

    • 回答としてマーク to1109 2016年11月21日 12:12
    • 回答としてマークされていない to1109 2016年11月21日 12:12
    2016年11月21日 12:12