non blocking Interlocked usage issue with Parallel (TPL) - c#

I am confused about the accuracy of code in multi threading as some time I am getting wrong result.
Looks like it might fail. Below is the code.
public class MyKeyValue
{
public double Key { get; set; }
public double Value { get; set; }
}
public class CollMyKeyValue : List<MyKeyValue>
{
public void SumUpValues(CollMyKeyValue collection)
{
int count =0;
Parallel.For(count, this.Count,
(i) =>
{
this[count].Value = this[count].Value + collection[count].Value;
Interlocked.Increment(ref count);
});
}
}
Assuming the keys are same in both collection.
I want add the values of one collection into another. Is it therad safe ?
I have not put the this[count].Value = this[count].Value + collection[count].Value; in thread safe block.

Just remove the interlocked increment :
public void SumUpValues(CollMyKeyValue collection)
{
//int count =0;
Parallel.For(0, this.Count,
(i) =>
{
this[i].Value = this[i].Value + collection[i].Value;
//Interlocked.Increment(ref count);
});
}
Your version is altering the index variable inside the loop. The For loop does this automatically; in the parallel version each thread gets an i (or set of i) to do, so incrementing in the loop makes no sense.

Not sure what you're trying to do. But I guess you mean this.
public void SumUpValues(CollMyKeyValue collection)
{
Parallel.For(0, this.Count, (i) =>
{
this[i].Value += collection[i].Value;
});
}
First parameter says the Parallel.For where to start, altering that makes no sense. You get i as the parameter to the loop body which will tell you which iteration you're in.

Related

C# Trying to wrap a function with a stopwatch

I've been attempting to see how long functions take to execute in my code as practice to see where I can optimize. Right now I use a helper class that is essentially a stopwatch with a message to check these. The goal of this is that I should be able to wrap whatever method call I want in the helper and I'll get it's duration.
public class StopwatcherData
{
public long Time { get; set; }
public string Message { get; set; }
public StopwatcherData(long time, string message)
{
Time = time;
Message = message;
}
}
public class Stopwatcher
{
public delegate void CompletedCallBack(string result);
public static List<StopwatcherData> Data { get; set; }
private static Stopwatch stopwatch { get; set;}
public Stopwatcher()
{
Data = new List<StopwatcherData>();
stopwatch = new Stopwatch();
stopwatch.Start();
}
public static void Click(string message)
{
Data.Add(new StopwatcherData(stopwatch.ElapsedMilliseconds, message));
}
public static void Reset()
{
stopwatch.Reset();
stopwatch.Start();
}
}
Right now to use this, I have to call the Reset before the function I want so that the timer is restarted, and then call the click after it.
Stopwatcher.Reset()
MyFunction();
Stopwatcher.Click("MyFunction");
I've read a bit about delegates and actions, but I'm unsure of how to apply them to this situation. Ideally, I would pass the function as part of the Stopwatcher call.
//End Goal:
Stopwatcher.Track(MyFunction(), "MyFunction Time");
Any help is welcome.
It's not really a good idea to profile your application like that, but if you insist, you can at least make some improvements.
First, don't reuse Stopwatch, just create new every time you need.
Second, you need to handle two cases - one when delegate you pass returns value and one when it does not.
Since your Track method is static - it's a common practice to make it thread safe. Non-thread-safe static methods are quite bad idea. For that you can store your messages in a thread-safe collection like ConcurrentBag, or just use lock every time you add item to your list.
In the end you can have something like this:
public class Stopwatcher {
private static readonly ConcurrentBag<StopwatcherData> _data = new ConcurrentBag<StopwatcherData>();
public static void Track(Action action, string message) {
var w = Stopwatch.StartNew();
try {
action();
}
finally {
w.Stop();
_data.Add(new StopwatcherData(w.ElapsedMilliseconds, message));
}
}
public static T Track<T>(Func<T> func, string message) {
var w = Stopwatch.StartNew();
try {
return func();
}
finally {
w.Stop();
_data.Add(new StopwatcherData(w.ElapsedMilliseconds, message));
}
}
}
And use it like this:
Stopwatcher.Track(() => SomeAction(param1), "test");
bool result = Stopwatcher.Track(() => SomeFunc(param2), "test");
If you are going to use that with async delegates (which return Task or Task<T>) - you need to add two more overloads for that case.
Yes, you can create a timer function that accepts any action as a delegate. Try this block:
public static long TimeAction(Action action)
{
var timer = new Stopwatch();
timer.Start();
action();
timer.Stop();
return timer.ElapsedMilliseconds;
}
This can be used like this:
var elapsedMilliseconds = TimeAction(() => MyFunc(param1, param2));
This is a bit more awkward if your wrapped function returns a value, but you can deal with this by assigning a variable from within the closure, like this:
bool isSuccess ;
var elapsedMilliseconds = TimeToAction(() => {
isSuccess = MyFunc(param1, param2);
});
I've had this problem a while ago as well and was always afraid of the case that I'll leave errors when I change Stopwatcher.Track(() => SomeFunc(), "test")(See Evk's answer) back to SomeFunc(). So I tought about something that wraps it without changing it!
I came up with a using, which is for sure not the intended purpose.
public class OneTimeStopwatch : IDisposable
{
private string _logPath = "C:\\Temp\\OneTimeStopwatch.log";
private readonly string _itemname;
private System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
public OneTimeStopwatch(string itemname)
{
_itemname = itemname;
sw.Start();
}
public void Dispose()
{
sw.Stop();
System.IO.File.AppendAllText(_logPath, string.Format($"{_itemname}: {sw.ElapsedMilliseconds}ms{Environment.NewLine}"));
}
}
This can be used a easy way
using (new OneTimeStopwatch("test"))
{
//some sensible code not to touch
System.Threading.Thread.Sleep(1000);
}
//logfile with line "test: 1000ms"
I only need to remove 2 lines (and auto format) to make it normal again.
Plus I can easily wrap multiple lines here which isn't possible without defining new functions in the other approach.
Again, this is not recommended for terms of few miliseconds.

how to fire a list of task in parallel c#

What would be he correct way to fire a list of task in parallel in a fire and forget manner.
What I've got below makes me believe that .WhenAll is blocking until all is done.
I've got quit a few like these, I need to learn how to loop and store all the called functions and then fire them off where the all run at the same time, it does not matter what function gets called first or last.
What is the correct approach for this?
I wish MS would put in their intellisense a little bit more info to help us out, because I've got more needs for async calls especially a lot of work calls at one time and they're all fire and forget.
Here is what I've got now.
public async static Task UpdateBayPositionAsync(string cadCNN, string bayPositions)
{
List<Task> myTask = new List<Task>();
string[] bps = bayPositions.Split(',');
int bID; byte pos;
for (int i = 0; i < bps.Length; i++)
{
bID = int.Parse(bps[i].Split(':')[0].ToString());
pos = byte.Parse(bps[i].Split(':')[1].ToString());
myTask.Add(Task.Run(() => { ElevationManagerDL.UpdateBayPosition(cadCNN, bID, pos); }));
};
await Task.WhenAll(myTask.ToList());
}
It looks like you are interested in both asynchronicity and parallelism
I would recommend solving the asynchronicity by a Task (not awaited) and the parallelism with Parallel.ForEach(..)
Parallel.ForEach is a lot more performant than to create one task per position,
especially if there are many positions, see Parallel.ForEach vs Task.Factory.StartNew
Something like this
public async static Task UpdateBayPositionAsync(string cadCnn, string serializedBayPositions)
{
string[] bayPositionsAsStrings = serializedBayPositions.Split(',');
List<BayPosition> bayPositions = bayPositionsAsStrings.Select(bp => new BayPosition(cadCnn, bp)).ToList();
Task.Factory.StartNew( () => Parallel.ForEach(bayPositions, item => item.Update()));
}
public class BayPosition
{
public int BId { get; private set; }
public byte Pos { get; private set; }
public string CadCnn { get; private set; }
public BayPosition(string cadCnn, string bayPosition)
{
string[] parameters = bayPosition.Split(':');
BId = Int32.Parse(parameters[0]);
Pos = Byte.Parse(parameters[1]);
CadCnn = cadCnn;
}
public void Update()
{
ElevationManagerDL.UpdateBayPosition(CadCnn, BId, Pos);
}
}
And if you only want the parallelism and want to block until all Updates are run then you just replace:
Task.Factory.StartNew( () => Parallel.ForEach(bayPositions, item => item.Update()));
with
Parallel.ForEach(bayPositions, item => item.Update());

Is this operation thread safe?

In the following example when the "Submit" button is clicked the value of the static variable Count is incremented. But is this operation thread safe? Is using Appliation object the proper way of doing such operation? The questions are applicable to Web form application s as well.
The count always seem to increase as I click the Submit button.
View(Razor):
#{
Layout = null;
}
<html>
<body>
<form>
<p>#ViewBag.BeforeCount</p>
<input type="submit" value="Submit" />
</form>
</body>
</html>
Controller:
public class HomeController : Controller
{
public ActionResult Index()
{
ViewBag.BeforeCount = StaticVariableTester.Count;
StaticVariableTester.Count += 50;
return View();
}
}
Static Class:
public class StaticVariableTester
{
public static int Count;
}
No, it's not. The += operator is done in 3 steps: read the value of the variable, increase it by one, assign the new value. Expanded:
var count = StaticVariableTester.Count;
count = count + 50;
StaticVariableTester.Count = count;
A thread could be preempted between any two of these steps. This means that if Count is 0, and two threads execute += 50 concurrently, it's possible Count will be 50 instead of 100.
T1 reads Count as 0.
T2 reads Count as 0
T1 adds 0 + 50
T2 adds 0 + 50
T1 assigns 50 to Count
T2 assigns 50 to Count
Count equals 50
Additionally, it could also be preempted between your first two instructions. Which means two concurrent threads might both set ViewBag.BeforeCount to 0, and only then increment StaticVariableTester.Count.
Use a lock
private readonly object _countLock = new object();
public ActionResult Index()
{
lock(_countLock)
{
ViewBag.BeforeCount = StaticVariableTester.Count;
StaticVariableTester.Count += 50;
}
return View();
}
Or use Interlocked.Add
public static class StaticVariableTester
{
private static int _count;
public static int Count
{
get { return _count; }
}
public static int IncrementCount(int value)
{
//increments and returns the old value of _count
return Interlocked.Add(ref _count, value) - value;
}
}
public ActionResult Index()
{
ViewBag.BeforeCount = StaticVariableTester.IncrementCount(50);
return View();
}
Increment is not atomic so is not thread safe.
Check out Interlocked.Add:
Adds two 32-bit integers and replaces the first integer with the sum, as an atomic operation.
You'd use it like this:
Interlocked.Add(ref StaticVariableTester.Count, 50);
Personally I'd wrap this in your StaticVariableTester class:
public class StaticVariableTester
{
private static int count;
public static void Add(int i)
{
Interlocked.Add(ref count, i);
}
public static int Count
{
get { return count; }
}
}
If you want the returned values (as per dcastro's comment) then you could always do:
public static int AddAndGetNew(int i)
{
return Interlocked.Add(ref count, i);
}
public static int AddAndGetOld(int i)
{
return Interlocked.Add(ref count, i) - i;
}
In your code you could do
ViewBag.BeforeCount = StaticVariableTester.AddAndGetOld(50);
If a method (instance or static) only references variables scoped within that method then it is thread safe because each thread has its own stack. You also can achieve thread safety by using any variety of synchronization mechanisms.
This operation is not thread safe because it uses shared variable: ViewBag.BeforeCount.
What Makes a Method Thread-safe? What are the rules?

Change normal loop to Parallel loop

I have the following code:
static void Main(string[] args)
{
TaskExecuter.Execute();
}
class Task
{
int _delay;
private Task(int delay) { _delay = delay; }
public void Execute() { Thread.Sleep(_delay); }
public static IEnumerable GetAllTasks()
{
Random r = new Random(4711);
for (int i = 0; i < 10; i++)
yield return new Task(r.Next(100, 5000));
}
}
static class TaskExecuter
{
public static void Execute()
{
foreach (Task task in Task.GetAllTasks())
{
task.Execute();
}
}
}
I need to change the loop in Execute method to paralle with multiple threads, I tried the following, but it isn't working since GetAllTasks returns IEnumerable and not a list
Parallel.ForEach(Task.GetAllTasks(), task =>
{
//Execute();
});
Parallel.ForEach works with IEnumerable<T>, so adjust your GetAllTasks to return IEnumerable<Task>.
Also .net has widely used Task class, I would avoid naming own class like that to avoid confusion.
Parallel.ForEach takes an IEnumerable<TSource>, so your code should be fine. However, you need to perform the Execute call on the task instance that is passed as parameter to your lambda statement.
Parallel.ForEach(Task.GetAllTasks(), task =>
{
task.Execute();
});
This can also be expressed as a one-line lambda expression:
Parallel.ForEach(Task.GetAllTasks(), task => task.Execute());
There is also another subtle bug in your code that you should pay attention to. Per its internal implementation, Parallel.ForEach may enumerate the elements of your sequence in parallel. However, you are calling an instance method of the Random class in your enumerator, which is not thread-safe, possibly leading to race issues. The easiest way to work around this would be to pre-populate your sequence as a list:
Parallel.ForEach(Task.GetAllTasks().ToList(), task => task.Execute());
This worked on my linqpad. I just renamed your Task class to Work and also returned an IEnumerable<T> from GetAllTasks:
class Work
{
int _delay;
private Work(int delay) { _delay = delay; }
public void Execute() { Thread.Sleep(_delay); }
public static IEnumerable<Work> GetAllTasks()
{
Random r = new Random(4711);
for (int i = 0; i < 10; i++)
yield return new Work(r.Next(100, 5000));
}
}
static class TaskExecuter
{
public static void Execute()
{
foreach (Work task in Work.GetAllTasks())
{
task.Execute();
}
}
}
void Main()
{
System.Threading.Tasks.Parallel.ForEach(Work.GetAllTasks(), new Action<Work>(task =>
{
//Execute();
}));
}

TPL with multiple Method calls Console.Write issue

If i use TPL i run into problems in Parse.. Methods i do use Console.Write to build some Line but somtimes one is to fast and writes in the other Methods row. How do i lock or is there some better way?
Parallel.Invoke(
() => insertedOne = Lib.ParseOne(list),
() => insertedTwo = Lib.ParseTwo(list),
() => insertedThree = Lib.ParseThree(list));
Example for Parse.. Methods.
public static int ParseOne(string[] _list) {
Console.Write("blabla");
Console.Write("blabla");
return 0;
}
public static int ParseTwo(string[] _list) {
Console.Write("hahahah");
Console.Write("hahahah");
return 0;
}
public static int ParseThree(string[] _list) {
Console.Write("egegege");
Console.Write("egegege");
return 0;
}
To be able to print your blablas, hahahahs and egegeges as a single entity(indivisible)
you can write your method as:
public static int ParseThree(string[] _list)
{
lock (Console.Out)
{
Console.Write("egegege");
Console.Write("egegege");
}
return 0;
}
Why don't you run all the tasks in one thread, one after the other?
System.Threading.Tasks.Task.Factory.StartNew(()=>
{
insertedOne = Lib.ParseOne(list);
insertedTwo = Lib.ParseTwo(list);
insertedThree = Lib.ParseThree(list);
});
This way you won't have that much of a race condition.

Categories

Resources