Nullable Property throwing NullReferenceException on .HasValue - c#

This line of (C#) code
if (!currentLap.S1.HasValue)
is giving me
System.NullReferenceException: Object reference not set to an instance of an object.
provided I'm sure that currentLap variable is instantiated (because it's being used a few lines before and it is a local variable) and it has following property:
private double? _s1;
[DefaultValue(null)]
[JsonConverter(typeof(ShortDoubleConverter))]
public double? S1
{
get { return _s1; }
set { _s1 = value; }
}
how can it possibly throw NullReferenceException? Can it be something to do with optimization on Release mode?
Thanks,
Stevo
EDIT:
here is full method code.
public void Update(DriverData driverData)
{
LapInfo currentLap = this.CurrentLap;
if (currentLap != null &&
this.LastDriverData != null &&
driverData.TotalLaps != this.LastDriverData.TotalLaps &&
driverData.InPits &&
driverData.Speed < 10 &&
!this.LastDriverData.InPits)
{
currentLap.Escaped = true;
}
this.LastDriverData = driverData;
if ((currentLap == null || currentLap.Lap != driverData.LapNumber) &&
!this.Laps.TryGetValue(driverData.LapNumber, out currentLap))
{
currentLap = new LapInfo() { Lap = driverData.LapNumber, Parent = this, Class = driverData.Class };
this.Laps.Add(driverData.LapNumber, currentLap);
int lapsCount = 0, completedDriverLaps = 0, cleanLaps = 0;
this.TotalLaps = driverData.TotalLaps;
//if it's not the first lap
if (driverData.TotalLaps > 0)
{
//previous lap
if (this.CurrentLap == null || !this.CurrentLap.Escaped)
{
this.CompletedLaps++;
if (this.CurrentLap == null || !this.CurrentLap.MaxIncident.HasValue)
this.CleanLaps++;
}
}
foreach (DriverLapsInfo laps in this.Parent.LapsByVehicle.Values)
{
lapsCount += laps.TotalLaps;
completedDriverLaps += laps.CompletedLaps;
cleanLaps += laps.CleanLaps;
}
this.Parent.Parent.SetLapsCount(driverData, lapsCount, driverData.Class, completedDriverLaps, cleanLaps);
}
this.CurrentLap = currentLap;
//add incidents
if (driverData.Incidents != null)
{
foreach (IncidentScore incident in driverData.Incidents)
{
this.CurrentLap.MaxIncident = Math.Max(this.CurrentLap.MaxIncident ?? 0, incident.Strength);
this.CurrentLap.Incidents++;
this.Incidents++;
}
}
LapInfo previousLap = null;
if ((this.PreviousLap == null || this.PreviousLap.Lap != driverData.TotalLaps) &&
this.Laps.TryGetValue(driverData.TotalLaps, out previousLap))
{
this.PreviousLap = previousLap;
if (!this.PreviousLap.Date.HasValue)
{
this.PreviousLap.Date = DateTime.UtcNow;
}
}
if (currentLap.Position == 0)
currentLap.Position = driverData.Position;
if (driverData.CurrentS1 > 0)
{
**if (!currentLap.S1.HasValue)**
{
this.UpdateBestS1(driverData.BestS1);
this.Parent.Parent.UpdateBestS1(driverData.BestS1, driverData.UniqueName);
currentLap.UpdateS1(driverData.CurrentS1, driverData);
//reset the best split set at the finish line
if (this.PreviousLap != null && this.PreviousLap.SplitBest < 0)
this.PreviousLap.SplitBest = 0;
}
if (driverData.CurrentS2.HasValue && driverData.CurrentS1.HasValue && !currentLap.S2.HasValue)
{
double s2 = driverData.CurrentS2.Value - driverData.CurrentS1.Value;
this.UpdateBestS2(s2);
this.Parent.Parent.UpdateBestS2(s2, driverData.UniqueName);
currentLap.UpdateS2(s2, driverData);
}
}
if (this.PreviousLap != null)
{
if (driverData.LastLap > 0)
{
if (!this.PreviousLap.S3.HasValue && driverData.LastS2.HasValue)
{
double s3 = driverData.LastLap.Value - driverData.LastS2.Value;
this.UpdateBestS3(s3);
this.Parent.Parent.UpdateBestS3(s3, driverData.UniqueName);
this.PreviousLap.UpdateS3(s3, driverData);
}
if (!this.PreviousLap.LapTime.HasValue)
{
double? bestLap = this.Parent.Parent.BestLap;
this.PreviousLap.UpdateLapTime(driverData, 0);
this.Parent.Parent.UpdateBestLap(this.PreviousLap, driverData.BestLap, driverData);
this.UpdateBestLap(driverData.BestLap, this.PreviousLap);
this.PreviousLap.UpdateLapTime(driverData, bestLap);
}
}
else
{
if (this.PreviousLap.SplitBest.HasValue)
this.PreviousLap.UpdateBestSplit();
if (this.PreviousLap.SplitSelf.HasValue)
this.PreviousLap.UpdateSelfSplit();
}
}
if (driverData.InPits)
{
switch (driverData.Sector)
{
case Sectors.Sector1:
if (previousLap != null)
previousLap.InPits = true;
break;
case Sectors.Sector3:
currentLap.InPits = true;
break;
}
}
//lap to speed
if (currentLap.TopSpeed < driverData.Speed)
{
driverData.TopSpeedLap = driverData.Speed;
currentLap.UpdateTopSpeed(driverData.Speed);
}
else
driverData.TopSpeedLap = currentLap.TopSpeed;
//overall top speed
if (this.TopSpeed < driverData.Speed)
{
driverData.TopSpeed = driverData.Speed;
this.TopSpeed = driverData.Speed;
this.Parent.Parent.UpdateTopSpeed(this.TopSpeed, driverData);
}
else
driverData.TopSpeed = this.TopSpeed;
}
There is no way on earth the code can make it to that line and currentLap beeing null.
Or am I going crazy? :)

.HasValue will not throw if the nullable reference is null, but a.b.HasValue will if a is null.
I suspect that currentLap == null. I know you say you're sure that currentLap is not null, but I think that's the most likely explanation. Can you post more code?
Update:
Thanks for posting your code.
This doesn't throw:
void Main() {
var f = new Foo();
Console.WriteLine (f.S1);
Console.WriteLine (f.S1.HasValue);
}
class Foo {
private double? _s1 = null;
public double? S1 {
get { return _s1; }
set { _s1 = value; }
}
}
Could you try to create a minimal reproduction? (minimal code that exhibits the issue)

Maybe have a look at the previous line of code :) - debugger often highlights the next line after the one where the NullReferenceException was actually thrown.

Related

C# - System.FormatException SQLite connection

I am experiencing an error that I cannot understand, can anyone explain to me what I am miserably doing wrong?
Database Table:
CREATE TABLE "posti_auto_mil" (
"n_posto" TEXT NOT NULL UNIQUE,
"id_utente" INTEGER NOT NULL,
"targa_1" TEXT NOT NULL,
"targa_2" TEXT NOT NULL,
"targa_3" TEXT NOT NULL,
"targa_4" TEXT NOT NULL,
"targa_5" TEXT NOT NULL,
"locazione" TEXT NOT NULL
);
LoadCar.cs
public static bool CheckTarga(int idUtente)
{
using (IDbConnection cnn = new SQLiteConnection(LoadConnectionString()))
{
var output = cnn.Query($"select * from utenti where id = {idUtente}").FirstOrDefault();
if (output != null)
{
var targa = cnn.Query($"select * from posti_auto_mil where id = {idUtente}").FirstOrDefault();
if (targa != null)
{
var checkpresenza = cnn.Query($"select locazione from posti_auto_mil where id_utente = {idUtente} limit 1");
if (checkpresenza.ToString() == "interno")
{
targaicon = 1;
}
else if (checkpresenza.ToString() == "esterno")
{
targaicon = 2;
}
else if (checkpresenza.ToString() == "provvisorio")
{
targaicon = 2;
}
else targaicon = 3;
}
return true;
}
else
{
targaicon = 3;
return false;
}
}
Form1.cs
//Parking
//Visibilità
listView_targheinfo.Items.Clear();
listView_targheinfo.Visible = true;
pictureBox_infobox.Visible = true;
if (Classi.LoadCar.CheckTarga(Int32.Parse(home_textBox_id.Text)) == true)
{
if (Classi.LoadCar.targaicon == 1)
{
pictureBox_infobox.BackgroundImage = global::RegistroAccessi_8Rgt.Properties.Resources.parking_32px_green;
}
else if (Classi.LoadCar.targaicon == 2)
{
pictureBox_infobox.BackgroundImage = global::RegistroAccessi_8Rgt.Properties.Resources.no_parking_32px;
}
else if (Classi.LoadCar.targaicon == 3)
{
pictureBox_infobox.BackgroundImage = global::RegistroAccessi_8Rgt.Properties.Resources.parking_32px_yellow;
}
else
{
pictureBox_infobox.BackgroundImage = global::RegistroAccessi_8Rgt.Properties.Resources.no_parking_32px;
}
}
else
{
pictureBox_infobox.BackgroundImage = global::RegistroAccessi_8Rgt.Properties.Resources.no_parking_32px;
}
Error:
I've done various tests but I don't understand what I'm doing wrong... can someone clarify this for me?
I can do a personnel search in the same way but I can't do it for vehicle number plates.

Visual Studio C# and Short-circuit evaluation

With the || Operator, Microsoft describes short circuit evaluation here Short Circuit Evaluation
However, I have the following code which seems to contradict this process:
if ((_opcLoaded || DoLoadOPC()) &&
(_tagsAdded || DoAddTags()) &&
DoWriteRecipe() &&
(DoResume()))
What I'm trying to prevent is the function DoAddTags from being called if _tagsAdded is true (DoAddTags sets _tagsAdded to true).
However, I'm finding that DoAddTags is called even when _tagsAdded is true. It's the same for _opcLoaded and DoLoadOPC. I've had to put a condition inside DoAddTags to check for _tagsAdded, which shouldn't be necessary.
Can someone explain why this is happening?
Here is the Complete Code
//
// Resume a Paused recipe
case MonitoredTasks.Resume:
Task.Factory.StartNew(() =>
{
MonitoredTask = MonitoredTasks.None;
if ((_opcLoaded || DoLoadOPC()) &&
**(_tagsAdded || DoAddTags())** &&
DoWriteRecipe() &&
(DoResume()))
{
MonitoredTask = MonitoredTasks.None;
RunningState = RecipeRunningStates.Running;
Status = CIPStatuses.Running;
}
else
{
MonitoredTask = MonitoredTasks.Resume;
}
});
break;
And the code for DoAddTags
/// <summary>
/// Adds all necessary tags to the OPC Server Manager
/// </summary>
/// <returns></returns>
bool DoAddTags()
{
bool result = false;
var oldActivity = Activity;
//
// Not doing anything OPC related?
if (Activity != CIPActivities.AddingOPCTags && !_tagsAdded && Activity != CIPActivities.StartingOPC)
{
lock (_locks[LOCK_OPC])
{
Activity = CIPActivities.AddingOPCTags;
Status = CIPStatuses.Initialising;
RecipeError = Errors.None;
try
{
//
// Reset connection and internal tags list
_serverManager.Reset();
//
// Now to add all OPC Tags - Area
CIPStatusTag = _serverManager.AddTag(_area.CIPStatusTag);
RecipeIDTag = _serverManager.AddTag(_area.RecipeIDTag);
RecipeInstructionIDTag = _serverManager.AddTag(_area.RecipeInstructionIDTag);
HandshakingTag = _serverManager.AddTag(_area.HandshakingTag);
GlobalInstructionIDTag = _serverManager.AddTag(_area.GlobalInstructionIDTag);
InstructionAttemptsTag = _serverManager.AddTag(_area.InstructionAttemptsTag);
//
// Area tags OK?
if (CIPStatusTag == null || RecipeIDTag == null || RecipeInstructionIDTag == null || HandshakingTag == null || GlobalInstructionIDTag == null || InstructionAttemptsTag == null)
{
RecipeError = Errors.InvalidAreaTags;
DoError(new RecipeErrorHandlerEventArgs(this) { Message = FormatMessage("CIPRecipe.DoAddTags - Invalid AREA Tags"), Sender = this });
}
else
{
VM_CIPInstruction vm = null;
bool instructionTagErrors = false;
//
// For each area instruction that is used, assig a link to the instruction
foreach (var i in _areaInstructions)
{
//
// Create a View Model for the specified area instruction : this allows us to determine the number of parameters (tags) that apply to the instruction
vm = new VM_CIPInstruction(i.Value.Instruction);
//
// Assign device reference tags
if (vm.DeviceReferencesAvailable)
{
i.Value.DeviceTag = _serverManager.AddTag(i.Value.Instruction.DeviceReferenceTag);
instructionTagErrors = i.Value.DeviceTag == null;
}
//
// For each required parameter, add tag
for (int paramNo = 1; paramNo <= vm.NoOfParams; paramNo++)
{
switch (paramNo)
{
case 1:
//
// Tag defined? Add it
if (vm.AreaInstruction.Param1Tag >= 0)
{
i.Value.Param1 = _serverManager.AddTag(i.Value.Instruction.Param1Tag);
if (i.Value.Param1 == null)
{
instructionTagErrors = true;
}
}
else
{
instructionTagErrors = true;
}
break;
case 2:
//
// Tag defined? Add it
if (vm.AreaInstruction.Param2Tag >= 0)
{
i.Value.Param2 = _serverManager.AddTag(i.Value.Instruction.Param2Tag);
if (i.Value.Param2 == null)
{
instructionTagErrors = true;
}
}
else
{
instructionTagErrors = true;
}
break;
case 3:
//
// Tag defined? Add it
if (vm.AreaInstruction.Param3Tag >= 0)
{
i.Value.Param3 = _serverManager.AddTag(i.Value.Instruction.Param3Tag);
if (i.Value.Param3 == null)
{
instructionTagErrors = true;
}
}
else
{
instructionTagErrors = true;
}
break;
case 4:
//
// Tag defined? Add it and then check quality
if (vm.AreaInstruction.Param4Tag >= 0)
{
i.Value.Param4 = _serverManager.AddTag(i.Value.Instruction.Param4Tag);
if (i.Value.Param4 == null)
{
instructionTagErrors = true;
}
}
else
{
instructionTagErrors = true;
}
break;
case 5:
//
// Tag defined? Add it and then check quality
if (vm.AreaInstruction.Param5Tag >= 0)
{
i.Value.Param5 = _serverManager.AddTag(i.Value.Instruction.Param5Tag);
if (i.Value.Param5 == null)
{
instructionTagErrors = true;
}
}
else
{
instructionTagErrors = true;
}
break;
case 6:
//
// Tag defined? Add it and then check quality
if (vm.AreaInstruction.Param6Tag >= 0)
{
i.Value.Param6 = _serverManager.AddTag(i.Value.Instruction.Param6Tag);
if (i.Value.Param6 == null)
{
instructionTagErrors = true;
}
}
else
{
instructionTagErrors = true;
}
break;
}
}
if (instructionTagErrors)
{
RecipeError = Errors.InvalidInstructionTags;
DoError(new RecipeErrorHandlerEventArgs(this) { Message = FormatMessage(String.Format("CIPRecipe.DoAddTags - Invalid Instruction {0} Tags", vm.Name)), Sender = this });
break;
}
}
//
// Any problems adding tags?
if (RecipeError == Errors.None)
{
Activity = CIPActivities.StartingOPC;
//
// Once all tags added, start OPC Server
result = _serverManager.Start();
if (!result)
{
Status = CIPStatuses.AddTagsFailed;
RecipeError = Errors.OPC;
DoError(new RecipeErrorHandlerEventArgs(this) { Message = FormatMessage("CIPRecipe.DoAddTags - Start of OPC failed"), Sender = this });
}
else
{
**_tagsAdded = true;**
Status = CIPStatuses.TagsAdded;
}
}
else
{
Status = CIPStatuses.AddTagsFailed;
}
}
}
catch (Exception ex)
{
RecipeError = Errors.Exception_AddTags;
DoError(new RecipeErrorHandlerEventArgs(this) { Message = FormatMessage("CIPRecipe.DoAddTags"), Exception = ex, Sender = this });
}
finally
{
Activity = oldActivity;
}
}
}
return Status == CIPStatuses.TagsAdded;
}
I've highlighted the relevant lines with **
On the first pass DoAddTags is executed and _tagsAdded set to TRUE- I've placed a breakpoint here, so I know it is being set. Shortly afterwards (with or without the former breakpoint) DoAddTags is again entered (on the first line) despite_doAddTags == true.
I've even set a breakpoint on the code "(_tagsAdded || DoAddTags())". _tagsAdded == true, yet DoAddTags is still entered.
So what I'm seeing is, and all the Watches/Debugging info is consistent with is that DoAddTags is being called whilst _tagsAdded == true
This code won't display the behavior you describe, the short-circuiting works just as described.
What actually happens: _tagsAdded is initially false, so DoAddTags() is called, which sets _tagsAdded to true.
Then the debugger kicks in, you inspect _tagsAdded and see it's true.
Instead step through your code using F11 and inspect or watch all relevant variables.

Invalid Data in Excel File. Index was outside the bounds of the array.C#

Cant find answer in any of the suggestions.I am trying to upload an excel file to the postgre Db.
Here is the C# code :
public static List<Common.Transactions.TransactionDetail> GetTransactionDetails(string path)
{
if (!File.Exists(path))
{
return null;
}
var transactionDetails = new List<Common.Transactions.TransactionDetail>();
foreach (var sheet in Workbook.Worksheets(path))
{
int officeId = 0;
foreach (var row in sheet.Rows.Skip(1))
{
var td = new Common.Transactions.TransactionDetail
{
GlAccountId = Core.GlAccounts.GetGlAcccountId(row.Cells[1]?.Text),
AccountNumberId = Deposit.AccountHolders.GetAccountNumberId(row.Cells[2]?.Text),
ShareAccountId = Core.ShareAccounts.GetShareAccountId(row.Cells[3]?.Text),
LoanId = Loan.LoanAccounts.GetLoanId(row.Cells[4]?.Text),
Debit = row.Cells[5]?.Text.ToDecimal(),
Credit = row.Cells[6]?.Text.ToDecimal(),
StatementReference = row.Cells[7]?.Text
};
if (row.Cells[7] != null)
{
td.OfficeId = Office.Offices.GetOfficeIdByCode(row.Cells[7]?.Text);
officeId = Office.Offices.GetOfficeIdByCode(row.Cells[7]?.Text);
}
if (td.AccountNumberId == 0)
{
td.AccountNumberId = null;
}
if (td.LoanId == 0)
{
td.LoanId = null;
}
if (td.ShareAccountId == 0)
{
td.ShareAccountId = null;
}
if (row.Cells[0] != null)
{
td.AccountName = row.Cells[0].Text;
}
if (row.Cells[1] != null && string.IsNullOrWhiteSpace(td.AccountName))
{
td.AccountName = row.Cells[1].Text;
}
if (row.Cells[2] != null && string.IsNullOrWhiteSpace(td.AccountName))
{
td.AccountName = row.Cells[2].Text;
}
if (row.Cells[3] != null && string.IsNullOrWhiteSpace(td.AccountName))
{
td.AccountName = row.Cells[3].Text;
}
#region OfficeId
if (td.AccountNumberId != null)
{
officeId = Deposit.AccountHolders.GetAccountOfficeId(td.AccountNumberId.ToLong());
}
if (td.LoanId != null)
{
officeId = Loan.LoanGrant.GetAccountOfficeId(td.LoanId.ToLong());
}
if (td.ShareAccountId != null)
{
officeId = Core.ShareAccounts.GetAccountOfficeId(td.ShareAccountId.ToLong());
}
#endregion
td.OfficeId = officeId != 0 ? officeId : SessionHelper.GetOfficeId();
td.OfficeCode = Office.Offices.GetOfficeCode(officeId);
transactionDetails.Add(td);
}
}
foreach (var detail in transactionDetails)
{
if (detail.Debit.ToDecimal() > 0 && detail.Credit > 0)
{
throw new TransactionDetailException(
$#"Invalid transaction. Either debit or credit should be null for '{detail.AccountName}'.");
}
if (detail.AccountNumberId > 0)
{
if (detail.Debit.ToDecimal() > 0)
{
if (detail.Debit > Deposit.AccountHolders.GetDepositAccountBalance(detail.AccountNumberId.ToLong()))
{
throw new TransactionDetailException(
$#"Insufficient balance in account '{detail.AccountName}'.");
}
}
detail.GlAccountId = Deposit.AccountHolders.GetGlAccountId(detail.AccountNumberId);
}
if (detail.ShareAccountId > 0)
{
if (detail.Debit.ToDecimal() > 0)
{
if (detail.Debit > Core.ShareAccounts.GetShareBalance(detail.ShareAccountId.ToLong()))
{
throw new TransactionDetailException(
$#"Insufficient balance in account '{detail.AccountName}'.");
}
}
detail.GlAccountId = Core.ShareAccounts.GetGlAccountId(detail.ShareAccountId.ToLong());
}
if (detail.LoanId > 0)
{
if (detail.Credit.ToDecimal() > 0)
{
if (detail.Credit > Loan.LoanAccounts.GetLoanCollectionBalance(detail.LoanId.ToLong(), Core.DateConversion.GetCurrentServerDate()))
{
throw new TransactionDetailException(
$#"Insufficient balance in account '{detail.AccountName}'.");
}
}
detail.GlAccountId = Loan.LoanGrant.GetLoanTransactionGLAccountId(detail.LoanId.ToLong());
}
detail.AuditUserId = Common.Helpers.SessionHelper.GetUserId();
detail.AccountNumberId = detail.AccountNumberId <= 0 ? null : detail.AccountNumberId;
detail.LoanId = detail.LoanId <= 0 ? null : detail.LoanId;
detail.ShareAccountId = detail.ShareAccountId <= 0 ? null : detail.ShareAccountId;
detail.EnableDeleteButton = true;
if (detail.GlAccountId == 0)
{
throw new TransactionDetailException($#"{detail.AccountName} is not a valid account.");
}
}
return transactionDetails;
}
}
I get error Index was outside the bounds of array.Invalid excel data.
My excel data
Gl Account Deposit A/C Share A/C Loan A/C Debit Credit Statement Reference
Loss Recovery Fund 0 1000 uploaded from excel
Risk Coverage Fund 0 1106 uploaded from excel
Ok solved it..The problem was with my excel data.
I was looking for row[7] which didnt exist.Had to add one column to the
excel file and it worked.
The exception was here in the code :
if (row.Cells[7] != null)
{
td.OfficeId = Office.Offices.GetOfficeIdByCode(row.Cells[7]?.Text);
officeId = Office.Offices.GetOfficeIdByCode(row.Cells[7]?.Text);
}
Thanks #LocEngineer Sir for your time.

Multithread, Linq to Sql, ConcurrentDictonary Fails Remove

I have a ConcurrentDictionary of Attributes for products. These attributes have the product ID and values for the names of the attribute and any options the attribute has. I have this ConcurrentDictionary because I have threads that are created to handle each attribute in the dictionary by attribute name.
if (knownAttribute.AttributeType.Value.Equals("Product Specification"))
{
Console.WriteLine("Started a thread for: " + knownAttribute.AttributeTypeId + ", " + knownAttribute.Value);
while (true)
{
/* if (AS400SpecificationAttributes.IsEmpty && knownSpecificationBag.IsEmpty && gatherRowsTasks.All(x => x.IsCompleted))
break;*/
AS400SpecificationAttribute AS400SpecificationAttributeWork = null;
AS400SpecificationAttributeWork = knownSpecificationBag.Keys.FirstOrDefault(x => x.AttributeName == knownAttribute.Value);
if (AS400SpecificationAttributeWork != null)
{
var product = ctx.Products.FirstOrDefault(x => x.ProductNumber == AS400SpecificationAttributeWork.ProductNumber);
if (product == null)
continue;
var productAttribute = new ProductAttribute();
productAttribute.Attribute = knownAttribute;
if (AS400SpecificationAttributeWork.AttributeValue != null)
{
var knownAttributeOption = ctx.AttributeOptions.FirstOrDefault(x => x.Attribute.Equals(knownAttribute) && x.Value.Equals(AS400SpecificationAttributeWork.AttributeValue));
if (knownAttributeOption == null)
{
knownAttributeOption = new AttributeOption();
knownAttributeOption.Value = AS400SpecificationAttributeWork.AttributeValue;
knownAttributeOption.Attribute = knownAttribute;
ctx.AttributeOptions.InsertOnSubmit(knownAttributeOption);
ctx.SubmitChanges();
}
productAttribute.AttributeOption = knownAttributeOption;
productAttribute.AttributeOptionId = knownAttributeOption.Id;
}
product.ProductAttributes.Add(productAttribute);
ctx.SubmitChanges();
string tmpstr = null;
if (!knownSpecificationBag.TryRemove(AS400SpecificationAttributeWork, out tmpstr))
Thread.Sleep(50);
}
else
{
if (tryCounter < 5)
{
tryCounter++;
Thread.Sleep(1000);
Console.WriteLine("Thread waiting for work: Product Specification:" + knownAttribute.Value);
continue;
}
else
{
int outVal;
threadTracker.TryRemove("Product Specification:" + knownAttribute.Value, out outVal);
Console.WriteLine("Closing Thread: Product Specification:" + knownAttribute.Value);
break;
}
}
Thread.Sleep(50);
}
It seems like the following Attribute element refuses to be removed.
I don't understand why. If i put it in a while(!dic.tryRemove(ele)) it will forever be stuck and never move from there.
There may be an error somewhere within the thread but I have no idea why.
This statement
if (!knownSpecificationBag.TryRemove(AS400SpecificationAttributeWork, out tmpstr))
will always return true or false. It won't block. That's the behavior of ConcurrentDictionary. It will return false if the key is not in the dictionary.
If you're looping while that method returns false and it's stuck, that means that the item isn't in the dictionary when the loop begins. Either it either was never in the dictionary or that another thread already removed it.
Is your intention to loop until the item is not in the dictionary?
You could try this:
if (!knownSpecificationBag.TryRemove(AS400SpecificationAttributeWork, out tmpstr)
&& !knownSpecificationBag.ContainsKey(AS400SpecificationAttributeWork))
Implement proper equals and gethashcode when using TryRemove
public override int GetHashCode()
{
return new { this.name, this.value, this.group, this.productNumber }.GetHashCode();
}
public bool Equals(AS400SpecificationAttribute other)
{
if (other == null)
return false;
return (this.ProductNumber.Equals(other.productNumber) && ((this.group != null && this.group.Equals(other.AttributeGroup)) || (this.group == null && other.AttributeGroup == null)) && ((this.name!= null && this.name.Equals(other.AttributeName)) || (this.name == null && other.AttributeName == null)) && ((this.value != null && this.value.ToUpper().Equals(other.AttributeValue.ToUpper())) || (this.value == null && other.AttributeValue == null)));
}

How to disable more than one NumericUpDown controls using one method?

i have a form with more than one NumericUpDown as controls to input answer. i want every input is true for an operation (multiplication, sum etc), NumericUpDown for that operation will be disable. i have used the code below (just for sum operation), but i think its not efficient because i have to make a method to check every operation.
private void IsSumTrue() {
if (add1 + add2 == sum.Value)
{
sum.Enabled = false;
}
}
private void IsDifferenceTrue()
{
if (add1 - add2 == difference.Value)
{
difference.Enabled = false;
}
}
private void IsProductTrue()
{
if (add1 * add2 == product.Value)
{
product.Enabled = false;
}
}
private void IsQuotientTrue()
{
if (add1 / add2 == quotient.Value)
{
quotient.Enabled = false;
}
}
anyone have idea how to make it more efficient with just a method for all operation?
below is my idea, but to check the value is true for every NumericUpDown i don't know how.
private void DisableIfValueIsTrue()
{
foreach(Control control in this.Controls)
{
NumericUpDown value = control as NumericUpDown;
// if(value [NEED HELP]
}
}
Considering your situtaion, you can set a tag for each NumericUpDown in design mode like this:
sum.Tag=1;
square.Tag=2;
etc
Then define some int variables:
int iSum=add1+add2;
int iSquare= //Whatever you want
etc
And finally loop through your controls this way:
foreach (NumericUpDown control in this.Controls.OfType<NumericUpDown>())
{
int intCondition = Convert.ToInt32(control.Tag) == 1
? iSum
: Convert.ToInt32(control.Tag) == 2
? iSquare
: Convert.ToInt32(control.Tag) == 3
? i3
: i4; //You should extend this for your 8 controls
control.Enabled = intCondition == control.Value;
}
OK! Second way I offer
Since you will have to always check 8 different conditions, you could simply forget about looping through the controls and just change your method like this:
private void DisableIfValueIsTrue()
{
sum.Enabled = add1 + add2 != sum.Value;
difference.Enabled= add1 - add2 != difference.Value;
product.Enabled= add1 * add2 != product.Value;
quotient.Enabled= (add2 !=0) && (add1 / add2 != quotient.Value);
//etc
}
I came across this while doing some research and would like to give my solution I used for my situation and hope it helps people. I needed minimum and maximum numbers for a calculation, so mine are named appropriately and I correlated these with some CheckBoxes. I used null in beginning of minimum and end of maximum to account for empty. I also had to create an event handler SubscribeToEvents() shown below.
In my load event for my form:
SubscribeToEvents();
_checkBoxs = new[] { cbXLight, cbLight, cbMedium, cbHeavy, cbXHeavy, cbXXHeavy, cbXXXHeavy };
_minimumsNumericUpDowns = new[] { null, nLightMin, nMediumMin, nHeavyMin, nXHeavyMin, nXXHeavyMin, nXXXHeavyMin };
_maximumsNumericUpDowns = new[] { nXLightMax, nLightMax, nMediumMax, nHeavyMax, nXHeavyMax, nXXHeavyMax, null };
then I created a method:
private void DisableNumericUpDowns()
{
// disable everything:
foreach (var n in _minimumsNumericUpDowns)
{
if (n != null)
n.Enabled = false;
}
foreach (var n in _maximumsNumericUpDowns)
{
if (n != null)
n.Enabled = false;
}
}
The event handler:
private bool _eventsSubscribed;
private void SubscribeToEvents()
{
if (_eventsSubscribed)
return;
_eventsSubscribed = true;
cbXXHeavy.CheckedChanged += CheckBox_NumericState;
cbXHeavy.CheckedChanged += CheckBox_NumericState;
cbXLight.CheckedChanged += CheckBox_NumericState;
cbHeavy.CheckedChanged += CheckBox_NumericState;
cbLight.CheckedChanged += CheckBox_NumericState;
cbMedium.CheckedChanged += CheckBox_NumericState;
cbXXXHeavy.CheckedChanged += CheckBox_NumericState;
}
Now I can used this to check when they are enabled and if they are greater than or less than 0 if needed in the method CheckBox:
private void CheckBox_NumericState(object sender, EventArgs e)
{
// disable everything
DisableNumericUpDowns();
// see if more than one checkbox is checked:
var numChecked = _checkBoxs.Count((cb) => cb.Checked);
// enable things if more than one item is checked:
if (numChecked <= 1) return;
// find the smallest and enable its max:
var smallest = -1;
for (var i = 0; i < _checkBoxs.Length; i++)
{
if (!_checkBoxs[i].Checked) continue;
if (_maximumsNumericUpDowns[i] != null)
{
_maximumsNumericUpDowns[i].Enabled = true;
}
smallest = i;
break;
}
// find the largest and enable its min:
var largest = -1;
for (var i = _checkBoxs.Length - 1; i >= 0; i--)
{
if (!_checkBoxs[i].Checked) continue;
if (_minimumsNumericUpDowns[i] != null)
{
_minimumsNumericUpDowns[i].Enabled = true;
}
largest = i;
break;
}
// enable both for everything between smallest and largest:
var tempVar = largest - 1;
for (var i = (smallest + 1); i <= tempVar; i++)
{
if (!_checkBoxs[i].Checked) continue;
if (_minimumsNumericUpDowns[i] != null)
{
_minimumsNumericUpDowns[i].Enabled = true;
}
if (_maximumsNumericUpDowns[i] != null)
{
_maximumsNumericUpDowns[i].Enabled = true;
}
}
}
So I can check each state as required:
I want to check if Extra Light is check:
// Extra Light
if (!cbXLight.Checked) return;
if (nXLightMax.Enabled == false)
{
_structCategoryType = XLight;
CheckStructureSheets();
}
else
{
if (nXLightMax.Value > 0)
{
_dMax = nXLightMax.Value;
_structCategoryType = XLight;
CheckStructureSheets();
}
else
{
MessageBox.Show(#"Extra Light Max cannot be zero (0)");
}
}
and next light checks both:
// Light
if (cbLight.Checked)
{
if (nLightMin.Enabled == false && nLightMax.Enabled == false)
{
_structCategoryType = Light;
CheckStructureSheets();
}
else
{
if (nLightMin.Enabled && nLightMin.Value > 0)
{
if (nXLightMax.Enabled && nLightMin.Enabled && nLightMax.Enabled == false)
{
_dMin = nLightMin.Value;
_structCategoryType = Light;
CheckStructureSheets();
}
else
{
if (nLightMax.Value > 0)
{
_dMin = nLightMin.Value;
_dMax = nLightMax.Value;
_structCategoryType = Light;
CheckStructureSheets();
}
else
{
MessageBox.Show(#"Light Max cannot be zero (0)");
return;
}
}
}
else if (nLightMin.Enabled == false && nLightMax.Enabled)
{
if (nLightMax.Value > 0)
{
_dMax = nLightMax.Value;
_structCategoryType = Light;
CheckStructureSheets();
}
else
{
MessageBox.Show(#"Light Max cannot be zero (0)");
}
}
else
{
MessageBox.Show(#"Light Min cannot be zero (0)");
return;
}
}
}
Hope this helps someone.
Tim
thanks for #AlexJoliq and #BrettCaswell. just want to inform that before Alex edited his answer from using "==" to "!=", i (thought) already solved the problem. but i don't know where is the more effective and efficient way, alex's or mine.
below is my code for DisableIfValueIsTrue():
if (add1 + add2 == sum.Value) sum.Enabled = false;
if (add1 - add2 == difference.Value) difference.Enabled = false;
if (add1 * add2 == product.Value) product.Enabled = false;
if (add1 / add2 == quotient.Value) quotient.Enabled = false;

Categories

Resources