Foreach loop and tasks - .net-4.0

I know from the codeing guidlines that I have read you should not do
for (int i = 0; i < 5; i++)
{
Task.Factory.StartNew(() => Console.WriteLine(i));
}
Console.ReadLine();
as it will write 5 5's, I understand that and I think i understand why it is happening. I know the solution is just to do
for (int i = 0; i < 5; i++)
{
int localI = i;
Task.Factory.StartNew(() => Console.WriteLine(localI));
}
Console.ReadLine();
However is something like this ok to do?
foreach (MyClass myClass in myClassList)
{
Task.Factory.StartNew(() => myClass.DoAction());
}
Console.ReadLine();
Or do I need to do the same thing I did in the for loop.
foreach (MyClass myClass in myClassList)
{
MyClass localMyClass = myClass;
Task.Factory.StartNew(() => localMyClass.DoAction());
}
Console.ReadLine();

It's absolutely the same problem with foreach. The following:
foreach (MyClass myClass in myClassList)
{
Task.Factory.StartNew(() => myClass.DoAction());
}
will most probably always invoke the DoAction method on the last element of the list, which could be fixed like this:
foreach (MyClass myClass in myClassList)
{
MyClass localMyClass = myClass;
Task.Factory.StartNew(() => localMyClass.DoAction());
}
But instead of relying on local variables I would recommend you the following:
for (int i = 0; i < 5; i++)
{
Task.Factory.StartNew(localI => Console.WriteLine(localI), i);
}

Related

Entity Framework not adding multiple objects

Im trying to add some dummy content into my database. I have a sample object called "obj", and I'm using a for loop to insert data like the code below:
public async Task<Post> Add(Post obj)
{
if (db != null)
{
obj.Id = 0;
for (int i = 0; i < 100; i++)
{
await db.Post.AddAsync(obj);
}
await db.SaveChangesAsync();
return obj;
}
return null;
}
However, it does add only 1 record into database, could you please explain what's wrong here?
Can you create object of post inside the loop and try again?
for (int i = 0; i < 100; i++)
{
Post obj = new Post();
await db.Post.AddAsync(obj);
}
If you run the below commands before calling saved changes you can see what changes EF Core has queued up.
var post = new Post();
for (int i = 0; i < 10; i++)
{
await db.Posts.AddAsync(dev);
}
db.ChangeTracker.DetectChanges();
Debug.WriteLine(db.ChangeTracker.DebugView.LongView);
await db.SaveChangesAsync();
This will write to Debug that one post is currently being tracked.
for (int i = 0; i < 10; i++)
{
var post = new Post();
await db.Posts.AddAsync(dev);
}
db.ChangeTracker.DetectChanges();
Debug.WriteLine(db.ChangeTracker.DebugView.LongView);
await db.SaveChangesAsync();
This will right to the Debug window the 10 posts are currently being tracked.
In your code when you AddAsync(obj), obj isn't a new object and EF Core is already tracking obj.
Moving Post obj = new Post() into the loop creates a new object for EF Core to track. If these objects aren't being added to the DB my guess would be that they don't meet a requirement for the Post model.
Either way playing around with
db.ChangeTracker.DetectChanges();
Debug.WriteLine(db.ChangeTracker.DebugView.LongView);
should help you be able to track down exactly what's going on.
I do hope you find this information helpful :)
You can try to use AddRange.
public async Task<Post> Add(Post obj)
{
if (db != null)
{
List<Post>=new List<Post>();
obj.Id = 0;
for (int i = 0; i < 100; i++)
{
l.Add(obj);
}
await db.Post.AddRangeAsync(l);
await db.SaveChangesAsync();
return obj;
}
return null;
}

ArrayList Method Returns a null ArrayList, main program cannot access

I'm trying to create a basic function that calls on a method that creates the 2D ArrayList that will be used further in the main program to do things like calculate the row and column sums as well as print out the triangle.
However, after it runs the ArrayList returns null. What's going on?
Thanks,
public class Trib
{
private ArrayList<ArrayList<Integer>> triangle;
private int Asize;
public Trib (int size)
{
// convert the argument to type 'int' to be used in the program
Asize = size;
// create an ArrayList of ArrayLists, it will have 'size' number ArrayLists contained within
ArrayList<ArrayList<Integer>> triangle = new ArrayList<ArrayList<Integer>>(size);
// create the inner ArrayLists
for (int i = 0; i < size; i++)
{
// add to index 'i' of our ArrayList a new ArrayList of size (i+1)
triangle.add(new ArrayList<Integer>(i+1));
for (int j = 0; j <= i; j++)
{
if (j==0 || j == i)
{
triangle.get(i).add(1);
}
else
triangle.get(i).add(triangle.get(i-1).get(j-1)+triangle.get(i-1).get(j));
System.out.print(triangle.get(i).get(j) + " ");
}
System.out.println();
}
triangle.clone();
}
public void printTriangle()
{
System.out.print(triangle.get(1).get(1));
/*for (int i = 0; i < Asize; i++)
{
for (int j = 0; j <= i; j++)
{
System.out.print(triangle.get(1).get(1) + " ");
}
System.out.println();
}*/
}
/*public Trib()
{
this(5);
}*/
/*public int Psize()
{
return triangle.size();
}
public ArrayList<Integer> sumRows()
{
ArrayList<Integer> row_sum = new ArrayList<Integer>(Asize);
for (int i = 0; i < Asize; i++)
{
for (int j = 0; j < i; j++)
{
row_sum.add(triangle.get(i).get(j));
}
}
return row_sum;
}
public ArrayList<Integer> sumCols()
{
ArrayList<Integer> col_sum = new ArrayList<Integer>(Asize);
for (int i = 0; i < Asize; i++)
{
for (int j = 0; j < i; j++)
{
col_sum.add(triangle.get(i).get(i));
}
}
return col_sum;
}*/
public static void main(String[] args)
{
if(args.length < 1)
{
System.err.println("Sorry, this program needs an integer argument.");
System.exit(1);
}
Trib pt = new Trib(Integer.parseInt(args[0]));
pt.printTriangle();
//ArrayList<Object> sum_rows = new ArrayList<Object>(pt.Psize());
// sum_rows.add;
System.out.println("\nHere are the sum of rows:");
//for (int i = 0; i < pt.Psize(); i++)
//System.out.println(sum_rows.get(i));
//ArrayList<Integer> sum_cols = new ArrayList<Integer>(pt.Psize());
System.out.println("\nHere are the sum of columns:");
//for (int i = 0; i < pt.Psize(); i++)
//System.out.printf("%-5d", sum_cols.get(i));
}
}
Watch out what's what you are doing: Notice that you have TWO variables named "triangle": The first one is an instance variable and the second is a local variable, which is the only one you have initialized.
My suggestion to avoid this common mistake is to pre-pend "this." to any use of what you intend must be an instance variable. And, if in doubt, if you use a development environment as Eclipse, press CTRL and click on your variable to navigate to the point where it is declared.

Roslyn - replace node and fix the whitespaces

In my program I use Roslyn and I need to replace a node with a new node. For example, if I have code like
public void Foo()
{
for(var i = 0; i < 5; i++)
Console.WriteLine("");
}
and I want to insert brackes for for statement, I get
public void Foo()
{
for(var i = 0; i < 5; i++)
{
Console.WriteLine("");
}
}
I tried to use NormalizeWhitespace, but if I use it on for statement, I get
public void Foo()
{
for(var i = 0; i < 5; i++)
{
Console.WriteLine("");
}
}
However, I'd like to have for statement formatted correctly. Any hints how to do it?
EDIT:
I solved it by using:
var blockSyntax = SyntaxFactory.Block(
SyntaxFactory.Token(SyntaxKind.OpenBraceToken).WithLeadingTrivia(forStatementSyntax.GetLeadingTrivia()).WithTrailingTrivia(forStatementSyntax.GetTrailingTrivia()),
syntaxNodes,
SyntaxFactory.Token(SyntaxKind.CloseBraceToken).WithLeadingTrivia(forStatementSyntax.GetLeadingTrivia()).WithTrailingTrivia(forStatementSyntax.GetTrailingTrivia())
);
However, the answer from Sam is also correct.
You need to use .WithAdditionalAnnotations(Formatter.Annotation), but only on the specific element you want to format. Here's an example from the NullParameterCheckRefactoring project.
IfStatementSyntax nullCheckIfStatement = SyntaxFactory.IfStatement(
SyntaxFactory.Token(SyntaxKind.IfKeyword),
SyntaxFactory.Token(SyntaxKind.OpenParenToken),
binaryExpression,
SyntaxFactory.Token(SyntaxKind.CloseParenToken),
syntaxBlock, null).WithAdditionalAnnotations(Formatter.Annotation, Simplifier.Annotation);

Why can't I get input from the ifstream?

I am trying to read in a text file for a maze program. The input is something like:
10 10
OO+E+OO+++
O++O+O+OOO
OOOOOO+O+O
+++++O++OO
OOO+OOO+O+
O+O+O+++O+
O+O+OOO+OO
++O+++O++O
O+OOOOO++O
O+O++O+OOO
When the user click on the open button, this opens a open file dialog box
{
openFileDialog1->InitialDirectory = "C:\Desktop;";
openFileDialog1->Filter = "Maze files (*.DAT)|*.DAT";
if (openFileDialog1->ShowDialog() == ::DialogResult::OK)
{
char filename[1024];
for (int i = 0; i < openFileDialog1->FileName->Length; i++)
{
filename[i] = openFileDialog1->FileName[i];
}
ifstream ifs;
ifs.open(filename); // NULL terminate this
maze = new Maze( panel1, ifs);
ifs.close();
}
}
the following is the maze constructor
Maze::Maze( Panel ^ drawingPanel, ifstream & ifs )
{
try
{
valid = false;
ifs >> width >> height;
int temp = width;
drawingPanel->Size.Width = width;
drawingPanel->Size.Height = height;
for (int i = 0; i < height; i++) // height is always nothing
for (int j = 0; j < width; j++)
{
if (orig[j][i] == DEADEND ||
orig[j][i] == OPEN ||
orig[j][i] == EXIT )
ifs >> orig[j][i]; // NULLS????
else
throw 'D'; // i had to throw something....so i threw the D /* make a slit class and throw the D there? slit.fill(D); */
}
// this should be last
panel = drawingPanel;
valid = true;
}
catch (...)
{
valid = false;
MessageBox::Show( "Not a proper maze file!" );
}
}
when the program runs: ifs >> width >> height width and height do not get set correctly.
I have searched this site for this problem and have not been able to find anything that has helped. Sorry for my inexperience, any help is greatly appreciated.
You'e program very ugly : don't know if you're programming in C or C++ or C++/CLI, or try to mix the 3...
Because you use Windows Form projet, i will give you a .Net solution for read a file, it's not the better solution but this does not mix things.
First for read the file, on a first window :
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e)
{
openFileDialog1->Filter = "Maze Files (*.dat) | *.dat";
if (openFileDialog1->ShowDialog() == ::DialogResult::OK)
{
String ^fileName = openFileDialog1->FileName;
IO::StreamReader ^myMazeFile = gcnew IO::StreamReader(fileName);
String ^content = myMazeFile->ReadToEnd();
richTextBox1->Text = content;
myMazeFile->Close();
// display button for open second form wich draw maze
button2->Visible = true;
}
}
now we have our file content, so we pass it to a second form who will draw the maze :
private: System::Void button2_Click(System::Object^ sender, System::EventArgs^ e)
{
String ^content = richTextBox1->Text;
Maze ^frm = gcnew Maze(content);
frm->Show();
}
Second window, create overload constructor :
Maze(String ^contentMap)
{
InitializeComponent();
String ^dimension = getWords(contentMap, 2);
array<String ^> ^coordsString = dimension->Split(gcnew array<Char> {' '});
m_width = Convert::ToInt32(coordsString[0]);
m_height = Convert::ToInt32(coordsString[1]);
panel1->Width = m_width;
panel1->Height = m_height;
}
getWords method :
String ^getWords(String ^input, int numWords)
{
try
{
int words = numWords;
for (int i = 0; i < input->Length; ++i)
{
if (input[i] == ' ' ||input[i] == '\n')
words--;
if (words == 0)
{
return input->Substring(0, i);
}
}
}
catch (Exception ^ex)
{
// ...
}
return String::Empty;
}
You have your dimension in full .Net (private member m_width and m_height).

Add A list Items to Combobox using Dispatcher.BeginInvoke()

I want to add a List to ComboBox through Dispatcher.BeginInvoke. But when I try to put it in a loop, only last value is loading.
private void LoadToComboBox(List<string> msg)
{
for (int i = 0; i < msg.Count; i++)
{
this.Dispatcher.BeginInvoke(() => cmbListItems.Items.Add(msg[i]));
}
}
The Dispatcher.BeginInvoke() is an asynchronous call. What is happening is that by the time you are calling your cmbListItems.Items.Add() function, it is already set to msg.Count.
Try something like this:
private void LoadToComboBox(List<string> msg)
{
this.Dispatcher.BeginInvoke(() =>
{
for (int i = 0; i < msg.Count; i++) {
cmbListItems.Items.Add(msg[i]);
}
});
}