[英]Thread synchronizing using Tasks and Parallel APIs
我粘貼了4個代碼段,其中嘗試使用以下API進行並行化:
Parallel.ForEach
Parallel.Invoke
Task.Run
Task.Factory.StartNew
問題嘗試並行化,以使有兩個for循環,內部循環和外部循環,並且每次執行外部循環時,內部循環中的所有內容都應在並行中執行。
我可以使用Parallel.ForEach
使其工作,其他所有原因都會導致內部計數器異常,該值超出了數組索引,而我認為情況並非如此。 索引也會比目標高一個值,例如,當索引的大小為500時,它會嘗試訪問值500,理想情況下它應該在499處停止。我是否錯過了什么。 以下是代碼段,請看一下:
並行ForEach(工作)
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace TestThreads
{
class Elements
{
public int innerValue;
public int outerValue;
public Elements(int innerValue, int outerValue)
{
this.innerValue = innerValue;
this.outerValue = outerValue;
}
}
class Program
{
private static int threadingCounter = 0;
private static int innerCounter = 500;
private static int outerCounter = 1000;
private static int[,] inOut;
private static int hitCount = 0;
private static int exceptionCount = 0;
private static List<int> innerCount = new List<int>();
static void Main(string[] args)
{
inOut = new int[innerCounter, outerCounter];
Program myProgram = new Program();
for (int iCount = 0; iCount < innerCounter; iCount++)
innerCount.Add(iCount);
try
{
for (int outer = 0; outer < outerCounter; outer++)
{
Parallel.ForEach<int>(innerCount, inner =>
{
myProgram.ThreadCall(new Elements(inner,outer));
}
);
Console.WriteLine("Main Thread Released Post Wait ...");
Console.WriteLine("Hit Count :: " + hitCount);
Console.WriteLine("Exception Count :: " + exceptionCount);
if (threadingCounter != 0)
Console.WriteLine("Threading Counter post Inner Loop :: " + threadingCounter);
}
}
catch (Exception ex)
{
Console.WriteLine("Exception :: " + ex.Message);
}
finally
{
if (innerCount != null)
innerCount = null;
}
}
public void ThreadCall(object state)
{
try
{
Interlocked.Increment(ref hitCount);
Elements localElement = (Elements)state;
int localInner = localElement.innerValue;
int localOuter = localElement.outerValue;
int finalValue = inOut[localInner, localOuter];
}
catch (Exception ex)
{
Console.WriteLine("Exception :: " + ex.Message);
}
}
}
}
Parallel.Invoke(由於索引值超出數組而失敗,嘗試獲取內部索引-500)
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace TestThreads
{
/// <summary>
///
/// </summary>
class Elements
{
public int innerValue;
public int outerValue;
public Elements(int innerValue, int outerValue)
{
this.innerValue = innerValue;
this.outerValue = outerValue;
}
}
/// <summary>
///
/// </summary>
class Program
{
private static int innerCounter = 500;
private static int outerCounter = 1000;
private static int[,] inOut;
private static int hitCount = 0;
private static int exceptionCount = 0;
private static List<Action> alSync = new List<Action>();
/// <summary>
///
/// </summary>
/// <param name="args"></param>
static void Main(string[] args)
{
inOut = new int[innerCounter, outerCounter];
Program myProgram = new Program();
try
{
for (int outer = 0; outer < outerCounter; outer++)
{
for (int inner = 0; inner < innerCounter; inner++)
alSync.Add(() => myProgram.ThreadCall(new Elements(inner, outer)));
Parallel.Invoke(alSync.ToArray());
alSync.Clear();
Console.WriteLine("Main Thread Released Post Wait ...");
Console.WriteLine("Hit Count :: " + hitCount);
Console.WriteLine("Exception Count :: " + exceptionCount);
}
}
catch (Exception ex)
{
Console.WriteLine("Exception :: " + ex.Message);
}
finally
{
if (alSync != null)
alSync = null;
}
}
/// <summary>
///
/// </summary>
/// <param name="state"></param>
public void ThreadCall(object state)
{
try
{
Interlocked.Increment(ref hitCount);
Elements localElement = (Elements)state;
int localInner = localElement.innerValue;
int localOuter = localElement.outerValue;
int finalValue = inOut[localInner, localOuter];
}
catch (Exception ex)
{
Interlocked.Increment(ref exceptionCount);
Console.WriteLine("Exception :: " + ex.Message);
}
}
}
}
Task.Run(由於索引值超出數組而失敗,嘗試獲取內部索引-500)
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace TestThreads
{
/// <summary>
///
/// </summary>
class Elements
{
public int innerValue;
public int outerValue;
public Elements(int innerValue, int outerValue)
{
this.innerValue = innerValue;
this.outerValue = outerValue;
}
}
/// <summary>
///
/// </summary>
class Program
{
private static int innerCounter = 500;
private static int outerCounter = 1000;
private static int[,] inOut;
private static int hitCount = 0;
private static int exceptionCount = 0;
private static List<Task> tlSync = new List<Task>();
/// <summary>
///
/// </summary>
/// <param name="args"></param>
static void Main(string[] args)
{
inOut = new int[innerCounter, outerCounter];
Program myProgram = new Program();
try
{
for (int outer = 0; outer < outerCounter; outer++)
{
for (int inner = 0; inner < innerCounter; inner++)
tlSync.Add(Task.Run(() => myProgram.ThreadCall(new Elements(inner, outer))));
Task.WaitAll(tlSync.ToArray());
tlSync.Clear();
Console.WriteLine("Main Thread Released Post Wait ...");
Console.WriteLine("Hit Count :: " + hitCount);
Console.WriteLine("Exception Count :: " + exceptionCount);
}
}
catch (Exception ex)
{
Console.WriteLine("Exception :: " + ex.Message);
}
finally
{
if (tlSync != null)
tlSync = null;
}
}
/// <summary>
///
/// </summary>
/// <param name="state"></param>
public void ThreadCall(object state)
{
try
{
Interlocked.Increment(ref hitCount);
Elements localElement = (Elements)state;
int localInner = localElement.innerValue;
int localOuter = localElement.outerValue;
int finalValue = inOut[localInner, localOuter];
}
catch (Exception ex)
{
Interlocked.Increment(ref exceptionCount);
Console.WriteLine("Exception :: " + ex.Message);
}
}
}
}
Task.Factory.StartNew(由於索引值超出數組而失敗,嘗試獲取內部索引-500)
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace TestThreads
{
/// <summary>
///
/// </summary>
class Elements
{
public int innerValue;
public int outerValue;
public Elements(int innerValue, int outerValue)
{
this.innerValue = innerValue;
this.outerValue = outerValue;
}
}
/// <summary>
///
/// </summary>
class Program
{
private static int innerCounter = 500;
private static int outerCounter = 1000;
private static int[,] inOut;
private static int hitCount = 0;
private static int exceptionCount = 0;
private static List<Task> tlSync = new List<Task>();
/// <summary>
///
/// </summary>
/// <param name="args"></param>
static void Main(string[] args)
{
inOut = new int[innerCounter, outerCounter];
Program myProgram = new Program();
try
{
for (int outer = 0; outer < outerCounter; outer++)
{
for (int inner = 0; inner < innerCounter; inner++)
tlSync.Add(Task.Factory.StartNew(() =>
myProgram.ThreadCall(new Elements(inner, outer))));
Task.WaitAll(tlSync.ToArray());
tlSync.Clear();
Console.WriteLine("Main Thread Released Post Wait ...");
Console.WriteLine("Hit Count :: " + hitCount);
Console.WriteLine("Exception Count :: " + exceptionCount);
}
}
catch (Exception ex)
{
Console.WriteLine("Exception :: " + ex.Message);
}
finally
{
if (tlSync != null)
tlSync = null;
}
}
/// <summary>
///
/// </summary>
/// <param name="state"></param>
public void ThreadCall(object state)
{
try
{
Interlocked.Increment(ref hitCount);
Elements localElement = (Elements)state;
int localInner = localElement.innerValue;
int localOuter = localElement.outerValue;
int finalValue = inOut[localInner, localOuter];
}
catch (Exception ex)
{
Interlocked.Increment(ref exceptionCount);
Console.WriteLine("Exception :: " + ex.Message);
}
}
}
}
不知道tlSync的用途是什么,我看不到為什么要將任務推送到通用列表。
如果您想做一些事情並更新用戶界面,則可以從我曾經寫過的表單程序中使用的這個功能中得到啟發
var ui = TaskScheduler.FromCurrentSynchronizationContext();
someList
.ForEach(f => Task.Factory.StartNew(() =>
{
// do stuff
})
.ContinueWith(task =>
{
if (task.IsCompleted)
{
// update UI
// called after each task above completes
}
}, ui));
或者您可能對內部/外部有關閉問題,可以嘗試更改此代碼
for (int inner = 0; inner < innerCounter; inner++)
tlSync.Add(Task.Factory.StartNew(() => myProgram.ThreadCall(new Elements(inner, outer))));
對此
for (int inner = 0; inner < innerCounter; inner++) {
var nInner = inner;
var nOuter = outer;
tlSync.Add(Task.Factory.StartNew(() => myProgram.ThreadCall(new Elements(nInner, nOuter))));
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.