Created
August 3, 2022 12:16
-
-
Save gekka/36c273a9d4ac01d78cc2f8f67925aa1b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace ConsoleApp1 | |
{ | |
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Text; | |
using System.Threading.Tasks; | |
using System.Collections.Concurrent; | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
//new Test<MyClassA, MyClassB>().Sample(); | |
ConcurrentBagTest(); | |
NormalEnumerableTest(); | |
} | |
static void ConcurrentBagTest() | |
{ | |
Console.WriteLine(nameof(ConcurrentBagTest)); | |
ConcurrentBag<int> cbag = new ConcurrentBag<int>(Enumerable.Range(1, 10)); | |
var t1 = Task.Run(() => | |
{ | |
System.Threading.Thread.Sleep(100); | |
System.Diagnostics.Debug.WriteLine("WAKE 1"); | |
// Task2の列挙の最中に削除したらどうなるか | |
while (cbag.Count > 0) | |
{ | |
cbag.TryTake(out var result); | |
} | |
// Task2の列挙の最中に追加したらどうなるか | |
cbag.AddRange(Enumerable.Range(11, 100)); | |
}); | |
foreach (int i in cbag) | |
{ | |
if (i == 5) | |
{ | |
t1.Wait(); //列挙途中に別スレッドで増減させてみる | |
} | |
Console.WriteLine($"Value={i} , Count={cbag.Count}"); | |
} | |
//結果 | |
// ConcurrentBag<T>は列挙の開始時点の状態に対して列挙が行われる。 | |
// 列挙の最中に追加・削除が行われても列挙に影響を受けない | |
} | |
static void NormalEnumerableTest() | |
{ | |
Console.WriteLine(nameof(NormalEnumerableTest)); | |
List<int> list = new List<int>(Enumerable.Range(1, 10)); | |
var t1 = Task.Run(() => | |
{ | |
System.Threading.Thread.Sleep(100); | |
System.Diagnostics.Debug.WriteLine("WAKE 2"); | |
// Task2の列挙の最中に削除したらどうなるか | |
list.Clear(); | |
// Task2の列挙の最中に追加したらどうなるか | |
list.AddRange(Enumerable.Range(11, 100)); | |
}); | |
try | |
{ | |
foreach (int i in list) | |
{ | |
if (i == 5) | |
{ | |
t1.Wait(); //列挙途中に別スレッドで増減させてみる | |
} | |
Console.WriteLine($"Value={i} , Count={list.Count}"); | |
} | |
} | |
catch (Exception ex) | |
{ | |
Console.ForegroundColor = ConsoleColor.Red; | |
Console.WriteLine(ex.Message); | |
Console.ResetColor(); | |
} | |
} | |
} | |
///////////////////////////////////////////////////////// | |
class Test | |
{ | |
List<MyClassA> list1 = new List<MyClassA>(); | |
List<MyClassB> list2 = new List<MyClassB>(); | |
public void Sample() | |
{ | |
AddDummy(list1, 100); | |
AddDummy(list2, 100); | |
ConcurrentBag<MyClassB> cbug = new ConcurrentBag<MyClassB>(); | |
var result = Parallel.ForEach(list1, (MyClassA data) => | |
{ | |
if (!IsAny(data, cbug)) | |
{ | |
// list2はParallel.ForEachの間は増減しないので | |
// このie2の寿命の間は増減しない | |
// ゆえに、このWhrereはConcurrentを処理せずとも良い | |
IEnumerable<MyClassB> ie2 = list2.Where(a => a.Member == data.Member); | |
cbug.AddRange(ie2); //ConcurrentBagに追加しても他の列挙には影響を与えない | |
} | |
}); | |
} | |
private bool IsAny(MyClassA data) | |
{ | |
// list2はParallel.ForEachの間は増減しないので | |
// こちらでも問題はない。 | |
return list2.Any(a => a.Member == data.Member); | |
} | |
private bool IsAny(MyClassA data, ConcurrentBag<MyClassB> cbug) | |
{ | |
// 列挙の最中に増減しても、Anyは列挙開始した時点の内容で処理される | |
return cbug.Any(a => a.Member == data.Member); | |
} | |
public void AddDummy<T>(List<T> list, int count) where T : ConsoleApp21.MyClassA, new() | |
{ | |
list.AddRange(Enumerable.Range(1, count).Select(i => new T() { Member = i.ToString() })); | |
} | |
} | |
class MyClassA | |
{ | |
public string Member { get; set; } | |
public override string ToString() => Member; | |
} | |
class MyClassB : MyClassA { } | |
static class Extension | |
{ | |
public static void AddRange<T>(this IProducerConsumerCollection<T> list, IEnumerable<T> source) | |
{ | |
foreach (T item in source) | |
{ | |
while (!list.TryAdd(item)) | |
{ | |
} | |
} | |
} | |
public static void AddRange<T>(this IProducerConsumerCollection<T> list, IEnumerable<T> source, System.Threading.CancellationToken token) | |
{ | |
foreach (T item in source) | |
{ | |
while (!list.TryAdd(item)) | |
{ | |
if (token.IsCancellationRequested) | |
{ | |
return; | |
} | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment