Good day to everyone.
Today I made up a school project with one thing bothering me.
My problem is, that I am passing argument to Thread function and when I print it to console via Console.WriteLine, it shows bad numbers.
for (i = 0; i < 10; i++) autari[i] = new Thread(() => autar(i));
for (i = 0; i < 10; i++) motorkari[i] = new Thread(() => motorkar(i + 10));
When I start them in same cycles, their functions do this:
static void motorkar(int id)
{
Console.WriteLine("motorkar {0}", id);
...
It is not the order problem, but when I pass for example 0. Visual studio in Debug writes to console number 2 and without Debug it writes 1.
What can be the problem? I know that I can solve this by setting string name, but I am confused with this.
This is due to the compiler creating you a closure under the hood. If you change the code around to the below you should get your expected output
for (i = 0; i < 10; i++)
{
var local = i;
autari[i] = new Thread(() => autar(local))
}
for (i = 0; i < 10; i++)
{
var local = i + 10;
motorkari[i] = new Thread(() => motorkar(local))
}
Related
I am working on a C# .NET core 3.1 application that needs to insert 300 - 500 million rows avro file data into a GBQ table. My idea is to batch insert the data using .Net Task to insert data asynchronously that doesn't block the main thread and when all tasks are finished, log the success or fail message. I did a sample code, if I use Task.Run(), it will break the batchId and lose some data. However, if using RunSynchronously works fine, but it will block the main thread and take some time, which is still acceptable. Just wondering if what's wrong with my code and is Task.Run() a good idea for my case. Thanks a lot! Here is my code: https://dotnetfiddle.net/CPKsMv Just in case, it doesn't work well, pasted here again:
using System;
using System.Collections;
using System.Threading.Tasks;
public class Program
{
public static void Main()
{
ArrayList forecasts = new ArrayList();
for(var k = 0; k < 100; k++){
forecasts.Add(k);
}
int size = 6;
var taskNum = (int) Math.Ceiling(forecasts.Count / (double) size);
Console.WriteLine("task number:" + taskNum);
Console.WriteLine("item number:" + forecasts.Count);
Task[] tasks = new Task[taskNum];
var i = 0;
for(i = 0; i < taskNum; i++) {
int start = i * size;
if (forecasts.Count - start < size) {
size = forecasts.Count - start;
}
// Method 1: This works well, but need take some time to finish
//tasks[i] = new Task(() => {
//var batchedforecastRows = forecasts.GetRange(start, size);
// GbqTable.InsertRowsAsync(batchedforecastRows);
//Console.WriteLine("batchID:" + (i + 1) + "["+string.Join( ",", batchedforecastRows.ToArray())+"]");
//});
// tasks[i].RunSynchronously();
// Method 2: will lose data: (94, 95) and batchId is messed
// Sample Print below:
// batchID:18 Inserted:[90,91,92,93]
// batchID:18 Inserted:[96,97,98,99]
tasks[i] = Task.Run(() => {
var batchedforecastRows = forecasts.GetRange(start, size);
// GbqTable.InsertRowsAsync(batchedforecastRows);
Console.WriteLine("batchID:" + (i + 1) + " Inserted:["+string.Join( ",", batchedforecastRows.ToArray())+"]");
});
}
}
}
This loop is executed
CoordPosition = new Func<string, int>[3];
for (int i = 0; i < CoordPosition.Length; i++)
{
CoordPosition[i] = (x => CapStringNumber(x, i));
}
When the method CapStringNumber is later executed by the funcs its second parameter has the value 3 for the entire array. I want it to be 0, 1, 2.
The following works:
CoordPosition = new Func<string, int>[3];
for (int i = 0; i < CoordPosition.Length; i++)
{
var localVariable = i;
CoordPosition[i] = (x => CapStringNumber(x, localVariable));
}
What is the proper way to achieve the effect I want? Making that localVariable seems a bit un-maintainable. I don't know javaScript but i'm told that 'IIFE' is a relevant javaScript term for this.
This question already has answers here:
For loop goes out of range [duplicate]
(3 answers)
Closed 8 years ago.
I have a for loop to create a number of Tasks that are perameterised:
int count = 16;
List<Tuple<ulong, ulong>> brackets = GetBrackets(0L, (ulong)int.MaxValue, count);
Task[] tasks = new Task[count];
s.Reset();
s.Start();
for(int i = 0; i < count; i++)
{
tasks[i] = Task.Run(() => TestLoop(brackets[i].Item1, brackets[i].Item2));
}
Task.WaitAll(tasks);
s.Stop();
times.Add(count, s.Elapsed);
However, when this runs, an exception is thrown by the line inside the For loop, that brackets[i] does not exist, because i at that point is 16, even though the loop is set to run while i < count.
If I change the line to this:
tasks[i] = new Task(() => TestLoop(brackets[0].Item1, brackets[0].Item2));
Then no error is thrown. Also, if I walk through the loop with breakpoints, no issue is thrown.
For repro, I also include GetBrackets, which just breaks a number range into blocks:
private List<Tuple<ulong, ulong>> GetBrackets(ulong start, ulong end, int threads)
{
ulong all = (end - start);
ulong block = (ulong)(all / (ulong)threads);
List<Tuple<ulong, ulong>> brackets = new System.Collections.Generic.List<Tuple<ulong, ulong>>();
ulong last = 0;
for (int i=0; i < threads; i++)
{
brackets.Add(new Tuple<ulong, ulong>(last, (last + block - 1)));
last += block;
}
// Hack
brackets[brackets.Count - 1] = new Tuple<ulong, ulong>(
brackets[brackets.Count - 1].Item1, end);
return brackets;
}
Could anyone shed some light on this?
(This is a duplicate of similar posts, but they're often quite hard to find and the symptoms often differ slightly.)
The problem is that you're capturing the variable i in your loop:
for(int i = 0; i < count; i++)
{
tasks[i] = Task.Run(() => TestLoop(brackets[i].Item1, brackets[i].Item2));
}
You've got a single i variable, and the lambda expression captures it - so by the time your task actually starts executing the code in the lambda expression, it probably won't have the same value as it did before. You need to introduce a separate variable inside the loop, so that each iteration captures a different variable:
for (int i = 0; i < count; i++)
{
int index = i;
tasks[i] = Task.Run(() => TestLoop(brackets[index].Item1, brackets[index].Item2));
}
Alternatively, use LINQ to create the task array:
var tasks = brackets.Select(t => Task.Run(() => TestLoop(t.Item1, t.Item2));
.ToArray(); // Or ToList
So I noticed that a treeview took unusually long to sort, first I figured that most of the time was spent repainting the control after adding each sorted item. But eitherway I had a gut feeling that List<T>.Sort() was taking longer than reasonable so I used a custom sort method to benchmark it against. The results were interesting, List<T>.Sort() took ~20 times longer, that's the biggest disappointment in performance I've ever encountered in .NET for such a simple task.
My question is, what could be the reason for this? My guess is the overhead of invoking the comparison delegate, which further has to call String.Compare() (in case of string sorting). Increasing the size of the list appears to increase the performance gap. Any ideas? I'm trying to use .NET classes as much as possible but in cases like this I just can't.
Edit:
static List<string> Sort(List<string> list)
{
if (list.Count == 0)
{
return new List<string>();
}
List<string> _list = new List<string>(list.Count);
_list.Add(list[0]);
int length = list.Count;
for (int i = 1; i < length; i++)
{
string item = list[i];
int j;
for (j = _list.Count - 1; j >= 0; j--)
{
if (String.Compare(item, _list[j]) > 0)
{
_list.Insert(j + 1, item);
break;
}
}
if (j == -1)
{
_list.Insert(0, item);
}
}
return _list;
}
Answer: It's not.
I ran the following benchmark in a simple console app and your code was slower:
static void Main(string[] args)
{
long totalListSortTime = 0;
long totalCustomSortTime = 0;
for (int c = 0; c < 100; c++)
{
List<string> list1 = new List<string>();
List<string> list2 = new List<string>();
for (int i = 0; i < 5000; i++)
{
var rando = RandomString(15);
list1.Add(rando);
list2.Add(rando);
}
Stopwatch watch1 = new Stopwatch();
Stopwatch watch2 = new Stopwatch();
watch2.Start();
list2 = Sort(list2);
watch2.Stop();
totalCustomSortTime += watch2.ElapsedMilliseconds;
watch1.Start();
list1.Sort();
watch1.Stop();
totalListSortTime += watch1.ElapsedMilliseconds;
}
Console.WriteLine("totalListSortTime = " + totalListSortTime);
Console.WriteLine("totalCustomSortTime = " + totalCustomSortTime);
Console.ReadLine();
}
Result:
I haven't had the time to fully test it because I had a blackout (writing from phone now), but it would seem your code (from Pastebin) is sorting several times an already ordered list, so it would seem that your algorithm could be faster to...sort an already sorted list. In case the standard .NET implementation is a Quick Sort, this would be natural since QS has its worst case scenario on already sorted lists.
Some time ago I did found an article about Action's being faster than pure method calls. I cannot remember where, but in the moment was shoked, did some tests and found it where true in some cases.
Today someone just said what I was testing was wrong, so, can someone find a cause to in these tests Action's without parameters are faster than pure methods? I must say it's only faster in x64 machines, in x86 are slower.
class Program
{
static void Main(string[] args)
{
test t = new test();
t.doTest();
Console.ReadKey();
}
}
class test
{
Stopwatch w;
int a = 0;
public void doTest()
{
Action doSum = () => { a = a + 1; };
Action<int> doSumValue = (add) => { a = a + add; };
w = new Stopwatch();
Console.WriteLine("-------With params-------");
for (int round = 0; round < 10; round++)
{
a = 0;
w.Reset();
w.Start();
for (int buc = 0; buc < 500000000; buc++)
sumValue(1);
w.Stop();
Console.WriteLine("Function: " + w.ElapsedMilliseconds);
a = 0;
w.Reset();
w.Start();
for (int buc = 0; buc < 500000000; buc++)
doSumValue(1);
w.Stop();
Console.WriteLine("Action: " + w.ElapsedMilliseconds);
}
Console.WriteLine("-------With no params---------");
for (int round = 0; round < 10; round++)
{
a = 0;
w.Reset();
w.Start();
for (int buc = 0; buc < 500000000; buc++)
sum();
w.Stop();
Console.WriteLine("Function: " + w.ElapsedMilliseconds);
a = 0;
w.Reset();
w.Start();
for (int buc = 0; buc < 500000000; buc++)
doSum();
w.Stop();
Console.WriteLine("Action: " + w.ElapsedMilliseconds);
}
}
void sum()
{
a = a + 1;
}
void sumValue(int toAdd)
{
a = a + toAdd;
}
}
EDIT: Changed loop count to surpase 1 sec with same results
The results on my machine (i7 2600) are these:
NEW RESULTS WITH A LOT OF ITERATIONS
-x86
*With params
Function: 1417ms
Action: 1568ms
*Without params
Function: 1422ms
Action: 1634ms
-x64
*With params
Function: 1976ms
Action: 2114ms
*Without params
Function: 1975ms
Action: 1719ms
OLD RESULTS WITH LOW ITERATION COUNT
-x86 With params
Function: 28ms
Action: 31ms
-x86 Without params
Function: 28ms
Action: 32ms
-x64 With params
Function: 39ms
Action: 42ms
-x64 With params
Function: 39ms
Action: 34ms
So, is my test wrong or actions are faster than calls to parameterless methods in x64 machines?
Action is a delegate. This, for all intents and purposes in .NET, is just a method pointer. i.e. it's just a pointer to a method, so logically it performs the same basic instructions and calls a method under the covers. There's no general reason why Action would be faster than a direct call to the same method wrapped by Action. There's many scenarios where it might be slightly slower because it's a level of abstraction around a method call--but not in a meaningful way.
Well, Henk Holterman had the key, I was running it in release mode but launching it from visual studio.
Launching it manually they behave at same speed, not action being faster (and with params being a lot slower).
Would love to find again that article here I did found this info to send him those results.
Thanks everyone.