2017-09-27 3 views
0

ラッパーはありません...C#Parallel.forはまだ右concurrentListとインデックスが、私はこの問題を持っていると私はこれが仕事を得るように見えることはできません

私はそれをスレッドセーフにする私のリストのラッパーを持っています。 しかし、引き続きparallel.forループ内でインデックスが機能しません。

 public ConcurrentList<ConcurrentList<string>> multipleData(ConcurrentList<string> Adresses, ConcurrentList<string> PostalCodes) 
    { 
     ConcurrentList<ConcurrentList< string>> data = new ConcurrentList<ConcurrentList<string>>(); 
     ServicePointManager.DefaultConnectionLimit = 100; 
     Parallel.For(0, Adresses.Count, new ParallelOptions { MaxDegreeOfParallelism = 100 }, i => 
     { 
      WebClient web = new WebClient(); 
      string textFromUrl = web.DownloadString("https://website1.com" + Adresses[i] + " " + PostalCodes[i]); 
      ConcurrentList<string> dataElement = new ConcurrentList<string>(); 
      if (textFromUrl.Split(':', ',')[1] == "1") 
      { 
       textFromUrl = web.DownloadString("https://website2.com" + textFromUrl.Split('"', '"')[11]); 
       textFromUrl = web.DownloadString("https://website3.com" + textFromUrl.Split('"', '"')[3]); 
       ConcurrentList<RootObject> obj = JsonConvert.DeserializeObject<ConcurrentList<RootObject>>(textFromUrl); 
       dataElement.Add(obj[0].hoofdadres.geocodeerServiceZoekString); 
       dataElement.Add(obj[0].gebruiksdoel); 
       dataElement.Add(obj[0].begindatum.ToString());  
      } 
      else 
      { 
       dataElement.Add("empty"); 
       dataElement.Add("empty"); 
       dataElement.Add("empty"); 
      } 
       data.Add(dataElement); 
     }); 
     return data; 
    } 

返されたデータをExcelシートにエクスポートします。問題は返されたデータが混ざり合っているため、反復0はデータ[0]にはなく、反復10はデータ[10]に収まらないということです。

マイ同時リストラッパー:

public class ConcurrentList<T> : IList<T>, IDisposable 
{ 
    #region Fields 
    private readonly List<T> _list; 
    private readonly ReaderWriterLockSlim _lock; 
    #endregion 

    #region Constructors 
    public ConcurrentList() 
    { 
     this._lock = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion); 
     this._list = new List<T>(); 
    } 

    public ConcurrentList(int capacity) 
    { 
     this._lock = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion); 
     this._list = new List<T>(capacity); 
    } 

    public ConcurrentList(IEnumerable<T> items) 
    { 
     this._lock = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion); 
     this._list = new List<T>(items); 
    } 
    #endregion 

    #region Methods 
    public void Add(T item) 
    { 
     try 
     { 
      this._lock.EnterWriteLock(); 
      this._list.Add(item); 
     } 
     finally 
     { 
      this._lock.ExitWriteLock(); 
     } 
    } 

    public void Insert(int index, T item) 
    { 
     try 
     { 
      this._lock.EnterWriteLock(); 
      this._list.Insert(index, item); 
     } 
     finally 
     { 
      this._lock.ExitWriteLock(); 
     } 
    } 

    public bool Remove(T item) 
    { 
     try 
     { 
      this._lock.EnterWriteLock(); 
      return this._list.Remove(item); 
     } 
     finally 
     { 
      this._lock.ExitWriteLock(); 
     } 
    } 

    public void RemoveAt(int index) 
    { 
     try 
     { 
      this._lock.EnterWriteLock(); 
      this._list.RemoveAt(index); 
     } 
     finally 
     { 
      this._lock.ExitWriteLock(); 
     } 
    } 

    public int IndexOf(T item) 
    { 
     try 
     { 
      this._lock.EnterReadLock(); 
      return this._list.IndexOf(item); 
     } 
     finally 
     { 
      this._lock.ExitReadLock(); 
     } 
    } 

    public void Clear() 
    { 
     try 
     { 
      this._lock.EnterWriteLock(); 
      this._list.Clear(); 
     } 
     finally 
     { 
      this._lock.ExitWriteLock(); 
     } 
    } 

    public bool Contains(T item) 
    { 
     try 
     { 
      this._lock.EnterReadLock(); 
      return this._list.Contains(item); 
     } 
     finally 
     { 
      this._lock.ExitReadLock(); 
     } 
    } 

    public void CopyTo(T[] array, int arrayIndex) 
    { 
     try 
     { 
      this._lock.EnterReadLock(); 
      this._list.CopyTo(array, arrayIndex); 
     } 
     finally 
     { 
      this._lock.ExitReadLock(); 
     } 
    } 

    public IEnumerator<T> GetEnumerator() 
    { 
     return new ConcurrentEnumerator<T>(this._list, this._lock); 
    } 

    IEnumerator IEnumerable.GetEnumerator() 
    { 
     return new ConcurrentEnumerator<T>(this._list, this._lock); 
    } 

    ~ConcurrentList() 
    { 
     this.Dispose(false); 
    } 

    public void Dispose() 
    { 
     this.Dispose(true); 
    } 

    private void Dispose(bool disposing) 
    { 
     if (disposing) 
      GC.SuppressFinalize(this); 

     this._lock.Dispose(); 
    } 
    #endregion 

    #region Properties 
    public T this[int index] 
    { 
     get 
     { 
      try 
      { 
       this._lock.EnterReadLock(); 
       return this._list[index]; 
      } 
      finally 
      { 
       this._lock.ExitReadLock(); 
      } 
     } 
     set 
     { 
      try 
      { 
       this._lock.EnterWriteLock(); 
       this._list[index] = value; 
      } 
      finally 
      { 
       this._lock.ExitWriteLock(); 
      } 
     } 
    } 

    public int Count 
    { 
     get 
     { 
      try 
      { 
       this._lock.EnterReadLock(); 
       return this._list.Count; 
      } 
      finally 
      { 
       this._lock.ExitReadLock(); 
      } 
     } 
    } 

    public bool IsReadOnly 
    { 
     get { return false; } 
    } 
    #endregion 
} 

public class ConcurrentEnumerator<T> : IEnumerator<T> 
{ 
    #region Fields 
    private readonly IEnumerator<T> _inner; 
    private readonly ReaderWriterLockSlim _lock; 
    #endregion 

    #region Constructor 
    public ConcurrentEnumerator(IEnumerable<T> inner, ReaderWriterLockSlim @lock) 
    { 
     this._lock = @lock; 
     this._lock.EnterReadLock(); 
     this._inner = inner.GetEnumerator(); 
    } 
    #endregion 

    #region Methods 
    public bool MoveNext() 
    { 
     return _inner.MoveNext(); 
    } 

    public void Reset() 
    { 
     _inner.Reset(); 
    } 

    public void Dispose() 
    { 
     this._lock.ExitReadLock(); 
    } 
    #endregion 

    #region Properties 
    public T Current 
    { 
     get { return _inner.Current; } 
    } 

    object IEnumerator.Current 
    { 
     get { return _inner.Current; } 
    } 
    #endregion 
} 

私はこれをどのように修正することができますか?このデータを使用してExcelにエクスポートしたいが、すべてのデータが混在している。

ありがとうございます。

+0

私は愚かだと感じます。もちろん、これはうまくいかず、スレッドは順番に開始しないので、私のリストは決して同期されません。 私はconcurrentdictionaryを使用し、これを解決しました。 申し訳ありません – Rick

答えて

1

ConcurrentListのラッパーに関する質問は実際にはありませんが、単に外部リソースからデータをロードするだけなので、それらに対して並列実行は必要ありません。
async-awaitを使用すると、効率的な方法で実行できます。読みやすくメンテナンス可能なコードとほぼ同時に使用できます。

あなたはリクエストの上アプローチの1つのコレクション

public async Task<IEnumerable<IEnumerable<string>> GetAll(
    IEnumerable<string> adresses, 
    IEnumerable<string> postalCodes) 
{ 
    // Start all tasks one by one without waiting for responses 
    var tasks = addresses.Zip(postalCodes, (addr, code) => GetData(addr, code)); 
    await Task.WhenAll(tasks); 

    return tasks.Select(task => task.Result).ToList(); 
} 

にすべて一緒になって「メイン」機能で

private static HttpClient client1; 
private static HttpClient client2; 
private static HttpClient client3; 
// HttpClient should be initialized once for whole application life-cycle 
// Execute code below somewhere in your initialization 
client1 = new HttpClient(); 
client1.BaseAddress = new Uri("https://website1.com"); 
client2 = new HttpClient(); 
client2.BaseAddress = new Uri("https://website2.com"); 
client3 = new HttpClient(); 
client3.BaseAddress = new Uri("https://website3.com"); 


public async Task<IEnumerable<string>> GetDataAsync(string address, string postalCode) 
{ 
    var path = $"{address} {postalCode}"; // build proper path for request 
    var textFrom1 = await client1.GetAsync(path); // Base address already added; 

    if (textFrom1.Split(':', ',')[1] != "1") 
    { 
     return Enumerable.Repeat("empty", 3); 
    } 

    var textFrom2 = await client2.GetAsync(textFrom1.Split('"', '"')[11]); 
    var textFrom3 = await client3.GetAsync(textFrom2.Split('"', '"')[3]); 

    var allData = JsonConvert.DeserializeObject<List<RootObject>>(textFrom3); 

    var item = allData.First(); 
    return new[] 
    { 
     item.hoofdadres.geocodeerServiceZoekString, 
     item.gebruiksdoel, 
     item.begindatum.ToString() 
    }; 
} 

そして、一つのアドレスの組と郵便番号のデータを取得するための非同期メソッドを作成/応答は並列と同じ速度で処理されますが、すべてが1つのスレッドで実行されるため、並行性と結果の同期について心配する必要はありません。

+0

あなたは王様です!これは速くてきれいに見えます。どうもありがとうございました!! – Rick

関連する問題