I am having trouble getting the synchronization of my managers and workers to go through correctly. The problem is that the SyncManager is stopping before the SyncWorker is done... And I don't know why it is continuing to execute without waiting for the SyncWorker to finish.
SyncManager
public void ExecuteTask()
{
/*Code to set up Variables*/
while (fileMetadata.Count > 0 && Status != WorkerStatus.ShouldStop)
{
if (DateTime.Now.Subtract(lastUpdate).Minutes > 1)
_serviceLog.WriteEntry(ProgressString());
if (Status == WorkerStatus.ShouldStop)
break;
SyncFile(fileMetadata[0]);
//Possible solution
//Wait for Sync File to Finish before stepping (although logically it should do that)
if (DateTime.Now.Subtract(lastUpdate).Minutes > 1)
_serviceLog.WriteEntry(ProgressString());
//Code That I think is causing the error
fileMetadata.RemoveAt(0);
}
/*Code to preform clean up actions and notify user of all transfers*/
}
public void SyncFile(FileMetadata fmd)
{
lock (executionLock)
{
attempts++;
long waitTime = 0;
switch (Type)
{
case (SyncManagerType.UploadLarge):
waitTime = 8192;
break;
case (SyncManagerType.UploadMedium):
waitTime = 4096;
break;
case (SyncManagerType.DownloadLarge):
waitTime = 8192;
break;
case (SyncManagerType.DownloadMedium):
waitTime = 4096;
break;
default:
waitTime = 30;
break;
}
syncWorker = new FileSyncWorker(GenerateSyncWorkerID(), _serviceLog, fmd, ref sb);
syncThread = new Thread(new ThreadStart(syncWorker.ExecuteTask));
syncThread.Start();
DateTime start = DateTime.Now;
DateTime finish;
while (DateTime.Now.Subtract(start).TotalSeconds < waitTime && (syncWorker.Status == WorkerStatus.Working))
{
if (DateTime.Now.Subtract(lastUpdate).Minutes > 1)
_serviceLog.WriteEntry(ProgressString());
if (Status == WorkerStatus.ShouldStop)
waitTime = 15;
Thread.Sleep(1000);
}
finish = DateTime.Now;
Thread.Sleep(1000);
if (finish.Subtract(start).TotalSeconds < waitTime)
{
if (syncWorker.Status == WorkerStatus.CompletedSuccess)
{
successes++;
}
}
else
{
syncThread.Abort();
sb.AppendLine("Sync Manager (" + ID + ") - FSW (" + syncWorker.ID + ") - Transfer timed out after " + waitTime + " seconds.");
}
//Possible Solution
//FileMetadata toRemove = fileMetadata.Find(delegate(FileMetadata f) { return f.Equals(syncWorker.FileData); });
//fileMetadata.Remove(toRemove);
activeIDs.RemoveAll(delegate(int i) { return i == syncWorker.ID; });
syncWorker = null;
Thread.Sleep(1000);
}
}
If you want the parent thread to wait for the worker make sure you put a Thread.Join before exiting:
if (finish.Subtract(start).TotalSeconds < waitTime)
{
if (syncWorker.Status == WorkerStatus.CompletedSuccess)
{
successes++;
}
}
else
{
syncThread.Abort();
syncThread.Join();
sb.AppendLine("Sync Manager (" + ID + ") - FSW (" + syncWorker.ID + ") - Transfer timed out after " + waitTime + " seconds.");
}
Related
I would like help.
There are some problems with the code.
I want to do only one inspection at a certain time every day.
In particular, the problem is the most serious in DateTime.Now.Hour == 11 part.
I am having difficulty checking certain times. I need to write code that can be checked only once at 11:00 in the whlie statement.
I created a license file and checked the date of the file.
public static CResult Dailytime(string date)
{
CResult result = new CResult();
if(result.nRet == 0)
{
while (true)
{
if (result.nRet == 1 || result.nRet == 2)
{
return result;
}
if (DateTime.Now.Hour == 11)
{
result = DailyCheckData(date);
if(result.nRet == 1 || result.nRet == 2)
{
return result;
}
}
System.Threading.Thread.Sleep(60 * 30 * 1000);
}
}
return result;
}
public static CResult DailyCheckData(string data)
{
CResult result = new CResult();
DateTime licenseDate = Convert.ToDateTime(data);
string dateNow = DateTime.Now.ToString("yyyy-MM-dd");
int compareDate = DateTime.Compare(Convert.ToDateTime(data), DateTime.Now);
if (licenseDate.ToString("yyyy-MM-dd") == dateNow)
{
result = ExpirationCertificate();
Console.WriteLine("Result = " + result.Result + " Msg = " + result.Msg + " nRet = " + result.nRet);
return result;
}
else
{
if (compareDate > 0)
{
result = TrueCertificate();
Console.WriteLine("Result = " + result.Result + " Msg = " + result.Msg + " nRet = " + result.nRet);
}
else if (compareDate <= 0)
{
result = ExpirationCertificate();
Console.WriteLine("Result = " + result.Result + " Msg = " + result.Msg + " nRet = " + result.nRet);
}
return result;
}
}
CResult class
nRet= 0 or 1 or 2
0 = fasle date
1 = false file
2 = true
Suggest or suggest ways to improve.
Can you try create a variable for DateTime.Now, after a line of code that value change.
DateTime licenseDate = Convert.ToDateTime(data);
string dateNow = DateTime.Now.ToString("yyyy-MM-dd");
int compareDate = DateTime.Compare(Convert.ToDateTime(data), DateTime.Now);
To
DateTime licenseDate = Convert.ToDateTime(data);
var now = DateTime.Now;
string dateNow = now.ToString("yyyy-MM-dd");
int compareDate = DateTime.Compare(licenseDate, now);
you shouldn't use Thread.Sleep() method for such a long duration. It is poor programming logic to make the thread sleep for such a long period.
What you can do to solve this is, is to make a Timer. There's an example attached in the link. A simple snippet to match your logic would be:
licenseStart = //setYours
lastCheck = DateTime.Now;
nextCheck = now.AddDays(1); // now.AddHours(1)
var timer = new Timer(o=>{/* Do work*/}, null, TimeSpan.Zero, nextCheck);
Hope it helps!
I asked about logic that can only loop once at 11 o'clock.
But I could not find the right answer and I found the answer.
I do not speak English well.
That's why others do not understand the intent of the question.
bool bOnce = true;
//bool s0nce = true;
while (true)
{
if (DateTime.Now.Hour == 11 && bOnce)
{
//run code
}
if (bOnce == true)
bOnce = false;
else
bOnce = true;
Thread.Sleep(10 * 60 * 1000);
}
I have a thread that is supposed to run continuously in my program and parse incoming serial data from a collection of sensors.
//initialized as a global variable
System.Threading.Thread processThread = new System.Threading.Thread(ProcessSerialData);
//this gets called when you press the start button
processThread.Start();
private void ProcessSerialData()
{
while (true)
{
//do a whole bunch of parsing stuff
}
int howDidYouGetHere = 0;
}
How is it possible that my program is reaching the "int howDidYouGetHere = 0" line??
Full code can be found here:
/// <summary>
/// ProcessSerialData thread will be used to continue testing the connection to the controller,
/// process messages in the incoming message queue (actually a linked list),
/// and sends new messages for updated data.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ProcessSerialData()
{
while (true)
{
UpdateAhTextbox(test.ampHoursOut.ToString());
if (!relayBoard.OpenConn())
{
MessageBox.Show("Connection to controller has been lost.");
testInterrupted = "Lost connection. Time = " + test.duration;
UpdateStatusText(false);
ShutErDown();
}
/////////////////////////////////////////////////////
if (incomingData.Count > 0)
{
string dataLine = "";
try
{
dataLine = incomingData.First();
UpdateParsedDataTextbox(dataLine + "\r\n");
}
catch (System.InvalidOperationException emai)
{
break; //data hasn't come in yet, it will by the time this runs next.
}
incomingData.RemoveFirst();
if (dataLine.Contains("GET")) // some sensor values (analog/temp/digital) has come in
{
if (dataLine.Contains("GETANALOG")) // an analog value has come in
{
int index = dataLine.IndexOf("CH");
int pin = (int)Char.GetNumericValue(dataLine[index + 2]);
double value = 0;
int dataLineLength = dataLine.Length;
if (dataLineLength > 13) // value is appended to end of line
{
try
{
value = Convert.ToDouble(dataLine.Substring(13));
}
catch // can't convert to double
{
int index2 = dataLine.IndexOf("CH", 3);
if (index2 != -1) // there happen to be two sets of commands stuck together into one
{
string secondHalf = dataLine.Substring(index2);
incomingData.AddFirst(secondHalf);
}
}
}
else // value is on the next line
{
try
{
value = Convert.ToDouble(incomingData.First());
incomingData.RemoveFirst();
}
catch // can't convert to double
{
MessageBox.Show("Error occured: " + dataLine);
}
}
switch (pin)
{
case 1:
ReadVoltage(value);
break;
case 2:
ReadAmperage(value);
break;
}
}
else if (dataLine.Contains("GETTEMP")) // received reply with temperature data
{
int index = dataLine.IndexOf("CH");
int pin = (int)Char.GetNumericValue(dataLine[index + 2]); // using index of CH, retrieve which pin this message is coming from
double value = 0;
int dataLineLength = dataLine.Length;
if (dataLineLength > 11) // value is appended to end of line
{
try
{
value = Convert.ToDouble(dataLine.Substring(11));
}
catch // can't convert to double
{
int index2 = dataLine.IndexOf("CH", 3);
if (index2 != -1) // there happen to be two sets of commands stuck together into one
{
string secondHalf = dataLine.Substring(index2);
incomingData.AddFirst(secondHalf);
}
}
}
else // value is on the next line
{
value = Convert.ToDouble(incomingData.First());
incomingData.RemoveFirst();
}
ReadTemperature(pin, value);
}
else // must be CH3.GET
{
int index = dataLine.IndexOf("CH");
int pin = (int)Char.GetNumericValue(dataLine[index + 2]); // using index of CH, retrieve which pin this message is coming from
if (pin == 3) // only care if it's pin 3 (BMS), otherwise it's a mistake
{
double value = 0;
int dataLineLength = dataLine.Length;
if (dataLineLength > 7) // value is appended to end of line
{
try
{
value = Convert.ToDouble(dataLine.Substring(7));
}
catch // can't convert to double
{
int index2 = dataLine.IndexOf("CH", 3);
if (index2 != -1) // there happen to be two sets of commands stuck together into one
{
string secondHalf = dataLine.Substring(index2);
incomingData.AddFirst(secondHalf);
}
}
}
else // value is on the next line
{
value = Convert.ToDouble(incomingData.First());
incomingData.RemoveFirst();
}
ReadBMS(value);
}
}
}
else if (dataLine.Contains("REL")) // received reply about relay turning on or off.
{
if (dataLine.Contains("RELS")) // all relays turning on/off
{
if (dataLine.Contains("ON"))
{
for (int pin = 1; pin <= 4; pin++)
{
test.contactors[pin] = true;
}
}
else // "OFF"
{
for (int pin = 1; pin <= 4; pin++)
{
test.contactors[pin] = false;
}
}
}
else // single relay is turning on/off
{
int index = dataLine.IndexOf("REL");
int pin = (int)Char.GetNumericValue(dataLine[index + 3]);
if (dataLine.Contains("ON"))
{
test.contactors[pin] = true;
}
else if (dataLine.Contains("OFF"))
{
test.contactors[pin] = false;
}
else if (dataLine.Contains("GET"))
{
if (Convert.ToInt32(incomingData.First()) == 1)
test.contactors[pin] = true;
else
test.contactors[pin] = false;
incomingData.RemoveFirst();
}
}
}
}
/////////////////////////////////////////////////////
// we only want more data if we're done processing the current data, otherwise we're stuck with too much and processing is heavily delayed.
if (isTestRunning && incomingData.Count < 3)
{
//read & output v, a, bms state
sendToController("CH1.GETANALOG"); // get voltage
sendToController("CH2.GETANALOG"); // get amperage
sendToController("CH3.GET"); // get BMS state
//read & output temperature
sendToController("CH4.GETTEMP"); // get temperature
sendToController("CH5.GETTEMP");
string lines = "Ah Out: " + test.ampHoursOut + ", Voltage: " + test.voltage +
", Amperage: " + test.amperage + ", Cell Temperature: " + test.tempBattery +
", Load Temperature: " + test.tempLoad;
WriteToLog(lines);
}
}
int howDidYouGetHere = 0;
}
The break (ignoring those inside the nested switch) breaks out of the while loop.
Perhaps you have tried to update your UI using UpdateParsedDataTextbox This will cause InvalidOperationException(then breaks the while loop) because you tries to access the UI control from thread that doesn't own the control.
Im having trouble learning how to loop, and Im stuck on how to do this. Basically I was asked to program that rolls a 6 sided die and it'll ask you how many times you want to roll it. Based on how many times you roll, it will out put a table of how many times it landed on each side. This is what I have so far.
using System;
namespace Dice
{
class Program
{
static void Main(string[] args)
{
bool continueRunning = true;
int sessionNumber = 1;
DisplayInstructions();
while (continueRunning)
{
int howMany = int.Parse(getInfo("How many times do you want to roll the die?"));
Dice aDice = new Dice();
aDice.RollDice();
Console.Clear();
Console.WriteLine("Session Number: {0}", sessionNumber);
Console.WriteLine(aDice);
continueRunning = getYorN("Would you like to run again?");
sessionNumber++;
Console.Clear();
}
}
public static bool getYorN(string question)
{
bool validInput = false;
while (!validInput)
{
Console.WriteLine("{0}", question);
Console.WriteLine("Enter 'yes' or 'no' to continue...");
string userResponse = Console.ReadLine().ToLower();
if (userResponse == "yes" || userResponse == "no")
{
validInput = true;
switch (userResponse)
{
case "yes":
return true;
case "no":
return false;
default:
return false;
}
}
else
{
Console.Clear();
Console.WriteLine("You've entered an invalid term");
}
}
return false;
}
public static void DisplayInstructions()
{
Console.WriteLine("Welcome to the Dice Game!!");
Console.WriteLine("\n\n\nThis program will simulate rolling a die and will track the frequency \neach value is rolled.");
Console.WriteLine("\n\n\nAfter rolling the die, the program will output a summary table for the session.");
Console.WriteLine("\n\n\nPlease press any key to continue.");
Console.ReadKey();
Console.Clear();
}
public static string getInfo(string what)
{
Console.WriteLine(what);
return Console.ReadLine();
}
}
}
The class I have in this is
using System;
namespace TripCalcApp
{
class Dice
{
private int side1 = 0, side2 = 0, side3 = 0, side4 = 0, side5 = 0, side6 = 0;
Random randNum = new Random();
public Dice()
{
}
public int Side1
{
get { return side1; }
set { side1 = value; }
}
public int Side2
{
get { return side2; }
set { side2 = value; }
}
public int Side3
{
get { return side3; }
set { side3 = value; }
}
public int Side4
{
get { return side4; }
set { side4 = value; }
}
public int Side5
{
get { return side5; }
set { side5 = value; }
}
public int Side6
{
get { return side6; }
set { side6 = value; }
}
public void RollDice()
//RollDice = randNum.Next(1, 7)
{
switch (randNum.Next(1, 7))
{
case 1: side1++;
break;
case 2: side2++;
break;
case 3: side3++;
break;
case 4: side4++;
break;
case 5: side5++;
break;
case 6: side6++;
break;
}
}
public override string ToString()
{
return " Freq. Rolls " +
"________________________________________" +
"\nSide 1 of Die rolled :" + side1 +
"\nSide 2 of Die rolled :" + side2 +
"\nSide 3 of Die rolled :" + side3 +
"\nSide 4 of Die rolled :" + side4 +
"\nSide 5 of Die rolled :" + side5 +
"\nSide 6 of Die rolled :" + side6 +
"\n";
}
}
}
I had an idea on how to do loop it but Im still unsure. I thought of something like this but it doesnt work and I was hoping you guys could help me!!
int howMany = int.Parse(getInfo("How many times would you like to roll the die?"));
do
{
Dice aDice = new Dice();
for (int counter = howMany; counter > 0; counter--)
{
aDice.RollDice();
}
while (howMany < 0)
{
Console.WriteLine(aDice);
}
Console.Clear();
Console.WriteLine("Session Number: {0}", sessionNumber);
Console.WriteLine(aDice);
playAgain = getYorN("Would you like to play again?");
sessionNumber++;
}
All you need to do is call aDice.RollDice method howMany times:
while (continueRunning)
{
int howMany = int.Parse(getInfo("How many times do you want to roll the die?"));
Dice aDice = new Dice();
for(int i = 0; i < howMany; i++)
{
aDice.RollDice();
}
Console.Clear();
Console.WriteLine("Session Number: {0}", sessionNumber);
Console.WriteLine(aDice);
continueRunning = getYorN("Would you like to run again?");
sessionNumber++;
Console.Clear();
}
I have a programming that is looping x times (10), and using a specified number of threads (2). I'm using a thread array:
Thread[] myThreadArray = new Thread[2];
My loop counter, I believe, starts the first 2 threads just fine, but when it gets to loop 3, which goes back to thread 0 (zero-based), it hangs. The weird thing is, if I throw a MessageBox.Show() in their to check the ThreadState (which shows thread 0 is still running), it will continue on through 9 of the 10 loops. But if no MessageBox.Show() is there, it hangs when starting the 3rd loop.
I'm using .NET 3.5 Framework (I noticed that .NET 4.0 utilizes something called continuations...)
Here's some code examples:
Thread[] threads = new Thread[2];
int threadCounter = 0;
for (int counter = 0; counter < 10; counter++)
{
if (chkUseThreading.Checked)
{
TestRunResult runResult = new TestRunResult(counter + 1);
TestInfo tInfo = new TestInfo(conn, comm, runResult);
if (threads[threadCounter] != null)
{
// If this is here, then it will continue looping....otherwise, it hangs on the 3rd loop
MessageBox.Show(threads[threadCounter].ThreadState.ToString());
while (threads[threadCounter].IsAlive || threads[threadCounter].ThreadState == ThreadState.Running)
Thread.Sleep(1);
threads[threadCounter] = null;
}
// ExecuteTest is a non-static method
threads[threadCounter] = new Thread(new ThreadStart(delegate { ExecuteTest(tInfo); }));
threads[threadCounter].Name = "PerformanceTest" + (counter + 1);
try
{
threads[threadCounter].Start();
if ((threadCounter + 1) == threadCount)
threadCounter = 0;
else
threadCounter++;
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
Application.DoEvents();
}
}
while (true)
{
int threadsFinished = 0;
for (int counter = 0; counter < threadCount; counter++)
{
if (!threads[counter].IsAlive || threads[counter].ThreadState == ThreadState.Stopped)
threadsFinished++;
}
if (threadsFinished == threadCount)
break;
else
Thread.Sleep(1);
}
Obviously the problem is something about how I'm checking to see if thread #1 or #2 is done. The IsAlive always says true, and the ThreadState always has "running" for threads loops 1 and 10.
Where am I going wrong with this?
Update, here's the ExecuteTask() method:
private void ExecuteTest(object tInfo)
{
TestInfo testInfo = tInfo as TestInfo;
Exception error = null;
DateTime endTime;
TimeSpan duration;
DateTime startTime = DateTime.Now;
try
{
if (testInfo.Connection.State != ConnectionState.Open)
{
testInfo.Connection.ConnectionString = connString;
testInfo.Connection.Open();
}
testInfo.Command.ExecuteScalar();
}
catch (Exception ex)
{
error = ex;
failedCounter++;
//if (chkCancelOnError.Checked)
// break;
}
finally
{
endTime = DateTime.Now;
duration = endTime - startTime;
RunTimes.Add(duration);
testInfo.Result.StartTime = startTime;
testInfo.Result.EndTime = endTime;
testInfo.Result.Duration = duration;
testInfo.Result.Error = error;
TestResults.Add(testInfo.Result);
// This part must be threadsafe...
if (lvResults.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(ExecuteTest);
this.Invoke(d, new object[] { tInfo });
}
else
{
lvResults.Items.Add(testInfo.Result.ConvertToListViewItem());
#region Update Results - This wouldn't work in it's own method in the threaded version
const string msPrefix = "ms";
// ShortestRun
TimeSpan shortest = GetShortestRun(RunTimes);
tbShortestRun.Text = shortest.TotalMilliseconds + msPrefix;
// AverageRun
TimeSpan average = GetAverageRun(RunTimes);
tbAverageRun.Text = average.TotalMilliseconds + msPrefix;
// MeanRun
TimeSpan mean = GetMeanRun(RunTimes);
tbMeanRun.Text = mean.TotalMilliseconds + msPrefix;
// LongestRun
TimeSpan longest = GetLongestRun(RunTimes);
tbLongestRun.Text = longest.TotalMilliseconds + msPrefix;
// ErrorCount
int errorCount = GetErrorCount(TestResults);
tbErrorCount.Text = errorCount.ToString();
#endregion
}
testInfo.Command.Dispose();
Application.DoEvents();
}
}
Can you post a snippet of run ()? Doesn't Thread.currentThread().notifyAll() help? May be each thread is waiting for other thread to do something resulting in a deadlock?
I am writing an app which uses a timer to display a countdown on screen to when some event happens. I want to reuse the timer, as it would be handy for a few things in the app, so I specify the words I want to wrap round the timer. For example, the following function call:
CountdownTimer(90, "You have ", " until the computer reboots");
would show:
You have 1 minute 30 seconds until the computer reboots
and then count down.
I am using the following code:
private void CountdownTimer(int Duration, string Prefix, string Suffix)
{
Countdown = new DispatcherTimer();
Countdown.Tick += new EventHandler(Countdown_Tick);
Countdown.Interval = new TimeSpan(0, 0, 1);
CountdownTime = Duration;
CountdownPrefix = Prefix;
CountdownSuffix = Suffix;
Countdown.Start();
}
private void Countdown_Tick(object sender, EventArgs e)
{
CountdownTime--;
if (CountdownTime > 0)
{
int seconds = CountdownTime % 60;
int minutes = CountdownTime / 60;
Timer.Content = CountdownPrefix;
if (minutes != 0)
{
Timer.Content = Timer.Content + minutes.ToString() + #" minute";
if (minutes != 1) { Timer.Content = Timer.Content + #"s"; }
Timer.Content = Timer.Content + " ";
}
if (seconds != 0)
{
Timer.Content = Timer.Content + seconds.ToString() + #" second";
if (seconds != 1) { Timer.Content = Timer.Content + #"s"; }
}
Timer.Content = Timer.Content + CountdownSuffix;
}
else
{
Countdown.Stop();
}
}
How do I make this run synchronously? For example I would want the following to wait 90 seconds and then reboot:
CountdownTimer(90, "You have ", " until the computer reboots");
ExitWindowsEx(2,0)
Whereas it calls the reboot immediately at present.
Any pointers would be most welcome!
Thanks,
Ben
Personally, I'd recommend having a callback happen at the end of your CountdownTimer - perhaps taking an Action as an argument, such that when it completed it'd be called.
private Action onCompleted;
private void CountdownTimer(int Duration, string Prefix, string Suffix, Action callback)
{
Countdown = new DispatcherTimer();
Countdown.Tick += new EventHandler(Countdown_Tick);
Countdown.Interval = new TimeSpan(0, 0, 1);
CountdownTime = Duration;
CountdownPrefix = Prefix;
CountdownSuffix = Suffix;
Countdown.Start();
this.onCompleted = callback;
}
...
else
{
Countdown.Stop();
Action temp = this.onCompleted; // thread-safe test for null delegates
if (temp != null)
{
temp();
}
}
Then you could just change your usage to:
CountdownTimer(90, "You have ", " until the computer reboots",
() => ExitWindowsEx(2,0));
You could use an AutoResetEvent:
System.Threading.AutoResetEvent _countdownFinishedEvent
= new AutoResetEvent(false);
Add this at the end of CountdownTimer:
_countdownFinishedEvent.WaitOne();
And add this inside the else of Countdown_Tick just after Countdown.Stop():
_countdownFinishedEvent.Set();