4

再生時に別のスレッドに列挙されるオブジェクト(音符)のリストがあります。UIスレッドの応答性を維持できるように、これを行っています。

ノートが再生されている間(列挙の一部として)、新しいノートがリストに追加される可能性があるという事実をどのように許可できますか(明らかなコレクション変更例外なしで)。

リストを一時的なリストにコピーして列挙できることはわかっていますが、実際には、ユーザーがさらに選択するにつれてリストを増やしたいと思っています(これは、最初のノートの再生中などに発生します)。

疑似ロジックはそのまま:

onClick()
{
 Queue.Add(theClickedNote)
 Queue.Play() <-- on another thread
}

Play()
{
 if(Playing==true){return ;}

 foreach(note theNote in Queue)
 {
  Note.Play();
  Queue.Remove(theNote);
 }
}

上記のように、各Clickイベントはキューにメモを追加してから、キューでplayメソッドを呼び出します。

キューはノートを列挙し、ノートを削除する前に各ノートを順番に再生します

私がやろうとしていることを明確に説明できたと思いますか?

4

3 に答える 3

4

このようなものはConcurrentQueue<T>、.Net4で使用できます。

ConcurrentQueue<Note> Queue = new ConcurrentQueue<Note>();

void onClick()
{
  Queue.Enqueue(theClickedNote);

  // start Play on another thread if necessary
}

void Play()
{
  if (Playing) return;

  Note note;
  while(Queue.TryDequeue(out note))
  {
     note.Play();
  }
}

ConcurrentQueueはスレッドセーフであるため、ロックを実装する必要はありません。

于 2012-06-03T19:17:55.543 に答える
0

リストを使用する代わりに、実際のキューを使用する必要があります。そうすると、コードは次のようになります。

    Queue<Note> queue = new Queue<Note>();
    void onClick()
    {
        queue.Enqueue(note);
    }

    void Play()
    {
        if (Playing == true) { return; }

        while (queue.Peek() != null)
        {
            var note = queue.Dequeue();
            note.play();
        }
    }

このコードはスレッドセーフではないため、キューにロックを追加する必要がありますが、これが一般的な考え方です。

于 2012-06-03T19:03:07.117 に答える
0

mike zが提案しているように、.NET 4.0で追加され たConcurrentQueue
を使用します 。他の同時コレクションとともに、このキューを使用すると、GetEnumeratorメソッドを使用して反復処理することにより、アイテムを非同期で追加/削除し、基になるコレクションのスナップショットを操作できます。 。キューが空であるなど、さまざまな状況に対処する必要がある場合があることに注意してください。これは、BlockingCollectionを介して解決できます。これは、コレクションが空である限り、takeメソッドがスレッドをブロックします。

于 2012-06-03T19:18:04.323 に答える