Parallel.For looping on the same value - c#

I'm trying to make a simple parallel.For and It seems to be getting the same "i" over and over again.
My code is:
String[] str = new String[10000];
Parallel.For(0,10000, i=>
{
if(str[i] == string.Empty)
str[i] = "ok";
else
str[i] = "SameValue";
});
I would expect it to never get to "else"

string.Empty does not equal null, change your if condition to
if (String.IsNullOrEmpty(str[i]))

I would expect it to never get to "else"
Wrong - the string array elements are initialized with null (their default value as reference type) - not string.Empty. Hence only the else part is ever executed.
You can easily verify this yourself by setting a break point on the if statement.

Related

Why Interlocked.CompareExchange is not working?

if (Interlocked.CompareExchange(ref this.popcount, this.popcount + 1, this.popcount) == this.popcount)
{
pop = Interlocked.CompareExchange(ref head, head.next, head);
}
I write a code but somehow it's not working as I wanted...
Interlocked.CompareExchange(ref this.popcount, this.popcount + 1, this.popcount)
I think this means
go to this.popcount reference and get value of popcount
compare value with this.popcount
if it is same, add 1 to this.popcount
Am I wrong? If I'm wrong, how can I correct it?
You need to remember the value that you added 1 to, the "before" value, and cannot rely on (re-) reading it from the variable you're going to change. Because the whole point is that multiple threads are competing to update this variable's value. So you want something like:
var oldcount = this.popcount;
var newcount = oldcount + 1;
if(Interlocked.CompareExchange(ref this.popcount, newcount, oldcount) == oldcount)
{
//It worked
}
else
{
//Loop round, try again, whatever you plan to do when you don't succeed.
}
With your example, even if the CompareExchange succeeds, you're then comparing the old value (returned by CompareExchange) to the new value (that you freshly read via this.popcount to the right of ==) and it's unlikely those will ever match. Conversely, they might be equal if your call to CompareExchange actually failed.
Of course, if you're just incrementing a variable, Interlocked.Increment would be more appropriate.

How to use value assigned within a for loop

I declare the variable setPassword outside of the loop and then give it a value within the loop. Then in the next do-while loop I try to use the value assigned but it says "Use of unassigned local variable".
profile[I] is an array of objects that are created prior to the loops. Is the value being assigned in the loop not saving or is the value of profile[I].Password null because the object hasn't been created yet?
bool good = false;
string username;
do
{
bool broke = false;
Console.WriteLine("Please create a username");
username = Console.ReadLine();
for (int i = 0; i < profile.Count; i++)
{
if (username == profile[i].Username)
{
Console.WriteLine("The username already exists");
broke = true;
break;
}
}
if (broke == false)
{
good = true;
}
} while (good == false);
Console.WriteLine("Please create a password");
string password = Console.ReadLine();
profile.Add(new Users(username, password, 0));
string setPassword;
bool validUser = false;
do
{
Console.Clear();
Console.WriteLine("Enter your username");
string tryUsername = Console.ReadLine();
for (int i = 0; i < profile.Count; i++)
{
if (profile[i].Username == tryUsername)
{
setPassword = profile[i].Password;
validUser = true;
}
}
if (validUser == false)
{
Console.WriteLine("Invalid username. Usernames are case sensitive");
Thread.Sleep(2500);
}
} while (validUser == false);
bool validPass = false;
do
{
Console.WriteLine("Enter your password");
string tryPass = Console.ReadLine();
if (tryPass == setPassword) //this is the error
{
validPass = true;
}
else
{
Console.WriteLine("Invalid password. Passwords are case sensitive");
}
} while (validPass == false);
The compiler can't know it will actually get assigned (and it doesn't if not all if statements you have evaluate to true).
Assign a default value and you will be fine:
string setPassword = null;
I initiate the variable setPassword outside of the loop and then give it a value within the loop.
This is the problem. The system cannot guarantee that a value is assigned before it is used.
It is possible that the loop iterates 0 times.
It is also possible that condition of the surrounding if statement evaluates to false.
Both of these situations lead to setPassword never getting a value.
So the compiler gives you an error, it is possible that you are using setPassword before it has a value.
The solution is to set it to a default value outside the loop, and outside the if.
This is because the compiler canĀ“t know that your for-loop is executed at least once and in particular that the if-statement within the loop also passes at least for one iteration of that loop. Thus - at least from the perspective of the compiler - it is possible that setPassword is never assigned a value and thus you get that error.
Assign null at the start:
string setPassword = null;
Basically the problem is this :
You are using them in mostly the if statements, the if statements uses a variable. But you only declared but never defined the variable globally/locally, which automatically gives an error, despite the variable will be taking a user's input locally, the if statement is unfortunately too stupid to detect that for you, plus it also takes the possibility that the user skips the step of giving an input too. Hence, you need to set a default value.
Like what they stated, you can use :
string setPassword = null; or string setPassword = "";
[Don't need to mind nullables , strings can be null by default]
To solve your problem, you should assign setPassword to string.Empty, null, or some other value, based on your use case
If you are curious about -
Why does the compiler complain that the variable is unassigned even though you assigned a value to it in while loop?
This is called the Definite Assignment behavior of the C# language. A variable is considered to be definitely assigned if
The variable was initialized at the time of declare - either with a default value or an explicitly value
Otherwise, if the compiler can prove, by static flow analysis (in simple words, compile time checks), that all possible execution paths leading up to the first use of variable will assign a value to the variable. Note, the static flow analysis is the key here, the compiler does not evaluate or take for granted that any run-time possibilities (conditions in if, while, for etc. control statements) will eventually assign the variable a value.
See Definite assignment at MSDN for more info. It is an archived document but should still be good a reference.
Also DotNetPerls Page describes it in simple language.
Disclaimer: I have no association with DotNetPerls.

Unassigned variable in return statement

for some reason I don't seem to be able to put the return in a fashion that captures this stored procedure's return value (0 or -1), either it returns the value which was used to initialize the variable or keeps telling me the local variable is unassigned.
public int changePass(int idUsuario, String old_pass, String new_pass)
{
int result;
try
{
DataTable tablaResultado =
DataBaseAccess.advanceStoredProcedureRequest(
"pa_usuario_change_pass",
new SPP[]
{
new SPP("id_usuario", idUsuario.ToString()),
new SPP("old_pass", old_pass.ToString()),
new SPP("new_pass", new_pass.ToString())
});
if (tablaResultado.Rows.Count > 0)
{
if (tablaResultado.Rows[0] != null)
{
result = (int.Parse(tablaResultado.Rows[0].ItemArray[0].ToString()));
}
}
return result;
}
catch (System.Data.SqlClient.SqlException sqlException)
{
throw sqlException;
}
}
I have multiple methods which follow the same pattern and all of those works, I have been trying to get this to work for awhile now, and I'm sure I'm overlooking something very, very obvious. Either way I cannot find it right now so I was hoping someone could refresh my memory or give me a tip.
The code only assigns a value to the result variable if two different conditions both happen to be true. That is, if the row count is > 0 and the first row is non-null. The compiler is telling you, completely legitimately, that your code contains a path to the return statement where the variable being used hasn't been assigned a value yet.
You need to decide what the method should return if either of those conditions are not true, and then assign that value to the result variable as part of its initialization.
EDIT:
To be clear: it seems you may be overlooking the possibility that your code won't successfully execute the stored procedure. But it can only return a value to be assigned to result when those two conditions are true. You either need to pick a default value that is reasonable to return when one or the other of the conditions aren't true, or you need to fix the code so that those conditions are always both true (and so the SP always executes successfully).

Is it even possible for the text property of a TextBox to be null?

I came across this code:
if (txtUPC.Text.ToString() != null)
...and wonder if this test is even valid - is it possible for the text property to be null? txtUPC is not a dynamically created control. It can be empty, of course, or contain just whitespace, but null? If so, I'd like to know how. Then again, call ToString() on the text property seems like wearing suspenders with a belt, too.
UPDATE
So it seems to me, that for me (remember: .NET 1.1, Windows CE/Compact Framework), this:
if (txtUPC.Text.Trim() != string.Empty)
...is a better test than this:
if (txtUPC.Text.ToString() != null)
However, upon gazing even more intently at this code, it seems that either the outer or the inner gauntlet is redundant/unnecessary, anyway. Note the two shibbeleth-pronunciation-checkers that the method includes:
if (txtUPC.Text.ToString() != null)
{
if (txtUPC.Text.Length > 0)
{
. . .
else
{
MessageBox.Show("Please enter a value in the item field");
txtUPC.Focus();
}
}
else
{
MessageBox.Show("Please enter a value in the item field");
txtUPC.Focus();
}
. . .
It would seem one gatekeeper/gauntleteer would be enough - either checking this way:
if (txtUPC.Text.Trim() != string.Empty)
...or this way:
if (txtUPC.Text.Trim().Length > 0)
a?
I don't think it could ever be null (perhaps there is a difference between a winforms/asp.net/wpf textbox, but I don't think so). Although a better check would be:
if (String.IsNullOrEmpty(txtUPC.Text) { ... }
Or, depending on your requirements:
if (String.IsNullOrWhiteSpace(txtUPC.Text) { ... }
And yes, the .ToString() is not needed.
The problem I see with that code is that .ToString() returns the object as a String. If in this case, the object is a String it just returns the original string (exactly as is)
Problem is if .Text is null, then the method call of .ToString() would throw a NullReferenceException.
You can see more on the .ToString override here
See this code for an example:
String str1 = "";
String str2 = null;
Console.WriteLine("Original str1: {0}", str1);
Console.WriteLine("Original str2: {0}", str2);
Console.WriteLine("ToString str1: {0}", str1.ToString());
Console.WriteLine("ToString str2: {0}", str2.ToString());
Will throw the exception on the ToString str2 line

How can this be not equal?

My Goal: Extracting one value from an Excel Range, and verify for these cells' value to be the same within this range;
When a cell's value is not the same as the other, I need to return null.
Here's a piece of code:
internal object GetValueFromCells(string start, string end, Formats format) {
// Verifying for empty or null parameters here and throwing accordingly...
try {
Range cells = Excel.get_Range(start, end) as Range;
object value = null;
bool sameValue = false;
foreach(Range cell in cells) {
// This condition block shall execute only once, since 'value' shall not be null afterwards.
if (value == null || value == DBNull.Value)
if (Formats.Formated == format) {
value = cell.Text;
// The following results to be false !?...
sameValue = value == cell.Text; // Shall this not be true?
} else {
value = cell.Value2;
// The following results to be false !?...
sameValue = value == cell.Value2; // Shall this not be true?
}
// This results being always false!?...
// Shall this not be true, I wonder?
sameValue = Formats.Formated == format ? value == cell.Text : value == cell.Value2;
if(!sameValue)
return null;
}
return value;
} catch (Exception ex) {
// Exception handling...
}
}
Reading this code, I would humbly expect a value to be returned when all of the cells in the range have the same value (for instance 334).
However, this methods always returns null (Nothing in Visual Basic)!
Anyone might explain what I'm missing here while this:
value == cell.Value2
always returns false?
Perhaps is it my algorithm that isn't quite right?
EDIT #1
This has solved the problem:
sameValue = Formats.Formatted == format ? cell.Text.Equals(value) : cell.Value2.Equals(value);
I accepted #Jerod Houghtelling's answer as his answer suggests both the ToString() and the Equals() methods to solve the problem.
In addition to it, I dislike having to call the ToString() method, since the value can be numbers, and comparing numbers under a string looks odd to me. So I prefer the Equals() way which I adopted within my solution.
I would like to thank #Sir Gallahad and #Jerod Houghtelling for their good answers. This was the first time I had to face such a situation, and they both helped me better understand what was going on under the hood, plus the others who contributed too through comments.
And thanks to those who upvoted my question. This serves a purpose to demonstrate that I was not so dumb asking! =P Hehehe...
I'm guessing that cell.Value2 is returning a new instance of an object each time you call it. Therefore I would deduce the == is checking to see if both sides of the equation are the same instance of the object. To actually compare the value stored on both side you will have to use the .Equals or convert the values to something that can be compared, for example a string.
sameValue = value.Equals( cell.Value2 );
/* or */
sameValue = value.ToString() == cell.Value2.ToString();
Also I don't see value being set in your example.
Probably the value == cell.Value2 are comparing objects that are from different instances.
Try value.ToString() == cell.Value2.ToString()

Categories

Resources