Hello I'm currently having an issue with a timer in a program I'm developing. The timer runs and calls methods which retrieve Windows Management Information from remote PC's after a set period of time and repeat this.
The first time the timer calls these all is well, however the second time, after the timer has completed its task, it loops through itself again and the third time it runs it does it 3 times etc. The for loop in the code below works fine its the timer itself.
So any help would be appareciated and if you require any further details please let me know.
Below is my code:
private void tmrStore_Tick(object sender, EventArgs e)
{
string ipAdd;
ipAdd = "127.0.0.1";
List<TblServer> Server;
WMIInfo localDB = new WMIInfo("Data Source=|DataDirectory|\\WMIInfo.sdf");
Server = localDB.TblServer.ToList();
if (Server.Count == 0)
{
}
else
{
for (int counter = 0; counter < Server.Count; counter++)
{
CPUStore cpu = new CPUStore();
cpu.Store(Server[counter].IpAdd);
HDDStore hdd = new HDDStore();
hdd.Store(Server[counter].IpAdd);
MemStore mem = new MemStore();
mem.Store(Server[counter].IpAdd);
//delete items over 24 hours old
}
}
Try disabling the timer before performing the management task, then reenabling:
tmrStore.Enabled = false;
try{
// do stuff
}finally{
tmrStore.Enabled = true;
}
The cause of the problem is probably that the body of your timer handler takes longer to execute than your Timer.Ticks value, so your timer events start to stack on top of each other.
You might also consider putting this code in a thread instead of a timer, so that it's independent of your user interface.
My first guess is that you are setting your Timer.Tick event in a place that is being executed multiple times. I would try searching for "tmrStore.Tick +=" to see where all the methods are being added to the event.
Right I've resolved the issue its because I had a class I was using to write the retrieved information into text boxes and within that I called a new instance of the form to gain access to the text boxes doh!
Thanks for your help though guys no doubt I'll be back soon for some more lol
Related
I need to write code in C# that sends data from Serial to an Arduino every 2 seconds.
This is what I tried to do:
Thread sender = new Thread(voidSender);
public static void voidSender() {
serialArduino.WriteLine("Test");
Thread.Sleep(2000);
}
In your example you are starting a thread running through the defined method, sending a single message. To send the message multiple times you need to add a loop to this method like
public void voidSender()
{
//Send forever
while(true)
{
serialArduino.WriteLine("Test");
Thread.Sleep(2000);
}
}
However, periodically events are typically done by using a timer. Simply initialize a timer like
System.Timers.Timer sendMessageTimer = new System.Timers.Timer(2000);
sendMessageTimer.Elapsed += OnSend;
sendMessageTimer.AutoReset = true;
sendMessageTimer.Enabled = true;
Inside the elapsed handler you can send the message like
private void OnSend(Object source, ElapsedEventArgs e)
{
serialArduino.WriteLine("Test");
}
Honestly I don't why you would mix open source platform such as Arduino with C# .net if its not running on core, but that's your concern not mine, I personally wouldn't do that.
if you want to send command every two seconds, I would advise you to use windows scheduler that's integrated in every windows system, however you can implement a clock on your own very easy, still why would you need to put such heavy load of 2 seconds timeframe when it will be almost notable by ordinary user. If you don't want to use clock based system you can use this modified example however it may throw stackoverflow exception sometime since its recursion and you must aways stay away from them if you plan to use this on the long run.
//First sorry for reusing your code but I am writing from my smartphone and
//I am kind of lazy here is quick modification that would work but not the most clever way around
Thread sender = new Thread(voidSender);
public static void voidSender()
{
start:
serialArduino.WriteLine("Test");
Thread.Sleep(2000);
goto start;
}
There's some strange mistake with timer and forms.
I am making editor for game. Editor has two forms - MainForm and PreviewForm. PreviewForm contains only control for OpenGL output (Custom control based on GLControl from OpenTK), named glSurface.
glSurface has two inline timers (Windows.Forms.Timer) - one for rendering, and one for updating game state. Timers fires in glSurface method Run(double updateRate, double frameRate).
So, I want to show PreviewForm and run updating and rendering from MainForm.
My code is:
PreviewForm = new PreviewForm();
PreviewForm.glSurface.Run(60d, 60d);
PreviewForm.Show(this); //Form is "modal"
Body of Run method:
if (Running)
throw new Exception("Already run");
_updateRate = updateRate;
_renderRate = frameRate;
var renderFrames = Convert.ToInt32(1000/frameRate);
var updateFrames = Convert.ToInt32(1000/updateRate);
RenderTimer.Interval = renderFrames;
UpdateTimer.Interval = updateFrames;
RenderTimer.Start();
UpdateTimer.Start();
Running = true;
Timers is being initialized in OnVisibleChanged event:
protected override void OnVisibleChanged(EventArgs e)
{
...
RenderTimer = new Timer();
UpdateTimer = new Timer();
RenderTimer.Tick += RenderTick;
UpdateTimer.Tick += UpdateTick;
...
}
Weird things start here.
When PreviewForm is showing, nothing happens. BUT when I close that form, both timers fire their events! I have tested for possible cross-thread interaction, but PreviewForm.InvokeRequired and glSurface.InvokeRequired are both false.
Please help me find out what the hell is going on.
In this case declare and initialise and start your timers all within the one code block:
{
.../...
RenderTimer = new Timer();
UpdateTimer = new Timer();
RenderTimer.Tick += RenderTick;
UpdateTimer.Tick += UpdateTick;
var renderFrames = Convert.ToInt32(1000/frameRate);
var updateFrames = Convert.ToInt32(1000/updateRate);
RenderTimer.Interval = renderFrames;
UpdateTimer.Interval = updateFrames;
RenderTimer.Start();
UpdateTimer.Start();
.../...
}
Without seeing the program flow this is the safest option. It appears the variables are local to the OnVisibleChanged event, so I'm not sure how you're not getting a null refernce exception when you're calling them from your if (Running).
The other thing you could do is make them class variables and ensure they are initialised before you use them. Then call start within the if statement.
As for the issue of them starting when the form closes, it's impossible to determine from the code you've shown.
Edit: There's a deeper problem.
You really shouldn't be using system timers to drive your game updates and rendering.
System timers on most platforms have low accuracy that's inadequate for high performance multimedia such as audio and most games. On Windows System.Windows.Forms.Timer uses Win32 timers which have particularly low accuracy, typically resulting in intervals at least 15ms off(see this answer). See this technical breakdown and this overview for more information. Basically, even if your code worked correctly your frames would stutter.
Most games "tick" by running an infinite loop in the main thread, doing the following each time(not necessarily in this order):
Call back into the framework to handle pending OS events.
Track the time difference since the last "tick" so frame-independent timing works.
Update the state of the game(such as physics and game logic, possibly in another thread).
Render the scene based on a previous update(possibly in another thread).
As noted by commenters, the main problem in your timer code is that initialization is split between Run and OnVisibleChanged. I was unable to reproduce the case where the timer fires after a sub form is closed. I suspect some other code you haven't posted is the cause. You'll save yourself a great deal of trouble if you use OpenTK.GameWindow. It handles the loop plumping for you, similar to XNA. This is an example of one way to integrate it with WinForms. See the manual for more information.
In Run, you set Interval and start each timer. No Tick callbacks are set. In OnVisibleChanged, you recreate the timers and assign Tick callbacks. No intervals are set, and the timer's haven't been started.
The timer initialization code in Run is essentially ignored because no tick callbacks are set and OnVisibleChanged recreates the timers. OnVisibleChanged triggers almost immediately after Run, shortly after you call PreviewForm.Show(this).
If you're dead set on using system timers, this should work:
// somewhere before Run(ideally in the initialization of the main form).
RenderTimer.Interval = Convert.ToInt32(1000 / frameRate);
RenderTimer.Tick += RenderTick;
UpdateTimer.Interval = Convert.ToInt32(1000 / updateRate);
UpdateTimer.Tick += UpdateTick;
void Run(double frameRate, double updateRate)
{
// ...
RenderTimer.Start();
UpdateTimer.Start();
// ...
Running = true;
}
// ...
protected override void OnVisibleChanged(EventArgs e)
{
// ...
// Don't initialize timers here.
// ...
}
I wrote an API that automates a certain website. However, on the testing stage, I noticed that (not very sure), my thread is not being terminated correctly.
I am using the WebBrowser object to navigate inside a thread, so that it works synchronously with my program:
private void NavigateThroughTread(string url)
{
Console.WriteLine("Defining thread...");
var th = new Thread(() =>
{
_wb = new WebBrowser();
_wb.DocumentCompleted += PageLoaded;
_wb.Visible = true;
_wb.Navigate(url);
Console.WriteLine("Web browser navigated.");
Application.Run();
});
Console.WriteLine("Thread defined.");
th.SetApartmentState(ApartmentState.STA);
Console.WriteLine("Before thread start...");
th.Start();
Console.WriteLine("Thread started.");
while (th.IsAlive) { }
Console.WriteLine("Journey ends.");
}
private void PageLoaded(object sender, WebBrowserDocumentCompletedEventArgs e)
{
Console.WriteLine("Pages loads...");
.
.
.
switch (_action)
{
.
.
.
case ENUM.FarmActions.Idle:
_wb.Navigate(new Uri("about:blank"));
_action = ENUM.FarmActions.Exit;
return;
case ENUM.FarmActions.Exit:
Console.WriteLine("Disposing wb...");
_wb.DocumentCompleted -= PageLoaded;
_wb.Dispose();
break;
}
Application.ExitThread(); // Stops the thread
}
Here is how I call this function:
public int Attack(int x, int y, ArmyBuilder army)
{
// instruct to attack the village
_action = ENUM.FarmActions.Attack;
//get the army and coordinates
_army = army;
_enemyCoordinates[X] = x;
_enemyCoordinates[Y] = y;
//Place the attack command
_errorFlag = true; // the action is not complated, the flag will set as false once action is complete
_attackFlag = false; // attack is not made yet
Console.WriteLine("Journey starts");
NavigateThroughTread(_url.GetUrl(ENUM.Screens.RallyPoint));
return _errorFlag ? -1 : CalculateDistance();
}
So the problem is, when I call the Attack function, couple times like this:
_command.Attack(509, 355, new ArmyBuilder(testArmy_lc));
_command.Attack(509, 354, new ArmyBuilder(testArmy_lc));
_command.Attack(505, 356, new ArmyBuilder(testArmy_lc));
_command.Attack(504, 356, new ArmyBuilder(testArmy_lc));
_command.Attack(504, 359, new ArmyBuilder(testArmy_lc));
_command.Attack(505, 356, new ArmyBuilder(testArmy_lc));
_command.Attack(504, 356, new ArmyBuilder(testArmy_lc));
_command.Attack(504, 359, new ArmyBuilder(testArmy_lc));
My application most of the times, gets stuck in one of these function (usually happens after the 4th or 5th). When it gets stuck the last log that I see is
Web browser navigated.
I assume it is something to do with termination of my thread. Can someone show me how I can run a thread which runs the DocumentCompleted event ?
I don't see any obvious reason for deadlock, nor did it reproduce at all when testing the code. There are a number of flaws in the code but nothing that yells "here!" loudly. I can only make recommendations:
Consider that you do not need a thread at all. The while (th.IsAlive) { } hot loop blocks your main thread while you wait for the browser code to finish the job. That is not a useful way to use a thread, you might as well use your main thread. This instantly eliminates a large number of potential hang causes.
The state logic in PageLoaded is risky. We cannot see all of it but one glaring issue is that you dispose the WebBrowser twice. If you have a case where you use return without a Navigate() call then you'll hang as described. No need to unsubscribe the event but same story, if you do unsubscribe but don't all Application.Exit() then you'll hang as described. State machines can be hard to debug, thorough logging is necessary. Minimize the risk by moving the Dispose() call and unsubscribing the event out of the logic, it doesn't belong there. And you need to test what happens when any Navigate() call ends up in failure, redirecting to a page you did not expect.
The _wb.Dispose() call is risky. Note that you destroy the WebBrowser while its DocumentCompleted event is in flight. Technically that can return code execution to code that is no longer alive or present. That can trip a race condition in the browser. As well as in the debugger, there is a dedicated MDA that checks for this problem. It is trivially avoided by moving the Dispose() call after the Application.Run() call where it belongs.
The while-loop burns 100% core, potentially starving the worker thread. Not a good enough reason to explain deadlock, but certainly unnecessary. Use Thread.Join() instead.
You create a lot of WebBrowser objects in this code. It is a very heavy object, as you can imagine, you need to keep an eye on memory usage in your program. Especially the unmanaged kind. If the browser leaks, like they so often do, you could technically create a scenario where the WB initializes okay but does not have enough memory left to load the page. Strongly favor using only one WB.
You need to consider that this might well be an environmental problem. On the top of that list is forever anti-malware and firewall, they always have a very good reason to treat a browser specially since that is the most common malware injection vector. You'll need to run your test with anti-malware and firewall disabled to ensure that it is not the cause of the hang.
Another environmental problem is one I noticed while testing this code, Google got sulky about me hitting it so often and started to throttle the requests, greatly slowing down the code. Talk to the web site owner and ask if he's got similar blocking or throttling counter-measures in place, most do. You need to test your state logic to verify that it still works properly when the browser redirects to an error page.
Yet another environmental issue is the WB will display a dialog itself in certain cases. This can deadlock in 3rd party code, very hard to diagnose. You should at least set the WebBrower.ScriptErrorsSuppressed to true but beware of Javascript code in the web page you load that itself creates new windows or displays alert dialogs. Using one WB is the workaround.
Keep in mind that your program can only be as reliable as your Internet connection and the web page server. That's not a terribly good place to be of course, both are quite out of your reach and you don't get nice exceptions to help you diagnose such a failure. And consider that you probably have not yet tested your program well enough yet to check if it can survive such a failure, it doesn't happen enough.
Quite a laundry list, focus first on eliminating the unnecessary thread and temporarily suppressing anti-malware. That's quick, focus next on using only one WebBrowser.
Hans thank you, I was able to fix this issue with one of your ideas. As you spent your time giving me a long answer, I wanted respond in same manner.
2 - I built the state machine structure carefully and with a lot logs (you can see it from my git account) also did a lot of debugs. I am sure that after I'm done navigating, I use Application.ExitThread() and wb.Dispose() only once.
3 - I tried placing the wb.Dispose() outside the event, however I couldn't find any other place where the Thread is still alive. If I try disposing WebBrowser outside the thread which is created inside the thread, the application gives me an error.
4 - I changed the code while (th.IsAlive) { } with th.Join(2000) this is absolutely a better idea but did not change anything. It optimized the code and as you mentioned, it prevented burning 100% core of my CPU.
5 - I tried using a single WebBrowser object which is instantiated in the constructor. However when I tried to navigate inside the thread, the application wouldnt even fire the events anymore. For some reason, I couldn't make it running whit a single WB object.
6,7 - I tested my application with different PC's and diffrent networks(with firewall and non-firewall protection). I changed windows firewall options as well but no travail. On my original code I do have _wb.ScriptErrorsSuppressed = true; so this shouldn't also be the issue.
8,9 - If these are the reasons, I can't do anything about it. But I doubt the real problem is caused because of them.
1 - This one was a good suggestion. I tried implementing my code without using a thread and it is now working fine. Here is how it looks like (still needs a lot optimization)
// Constructer
public FarmActions(string token)
{
// set the urls using the token
_url = new URL(token);
// define web browser properties
_wb = new WebBrowser();
_wb.DocumentCompleted += PageLoaded;
_wb.Visible = true;
_wb.AllowNavigation = true;
_wb.ScriptErrorsSuppressed = true;
}
public int Attack(int x, int y, ArmyBuilder army)
{
// instruct to attack the village
_action = ENUM.FarmActions.Attack;
//get the army and coordinates
_army = army;
_enemyCoordinates[X] = x;
_enemyCoordinates[Y] = y;
//Place the attack command
_errorFlag = true; // the action is not complated, the flag will set as false once action is complete
_attackFlag = false; // attack is not made yet
_isAlive = true;
Console.WriteLine("-------------------------");
Console.WriteLine("Journey starts");
NavigateThroughTread(_url.GetUrl(ENUM.Screens.RallyPoint));
return _errorFlag ? -1 : CalculateDistance();
}
private void NavigateThroughTread(string url)
{
Console.WriteLine("Defining thread...");
_wb.Navigate(url);
while (_isAlive) Application.DoEvents();
}
private void PageLoaded(object sender, WebBrowserDocumentCompletedEventArgs e)
{
Console.WriteLine("Pages loads...");
.
.
.
switch (_action)
{
.
.
.
case ENUM.FarmActions.Idle:
_wb.Navigate(new Uri("about:blank"));
_action = ENUM.FarmActions.Exit;
return;
case ENUM.FarmActions.Exit:
break;
}
_isAlive = false;
}
This is how I was able to wait without using a thread.
The main problem was probably as you mentioned in number 3 or 5. But I wasn't able to fix the problem as I spent couple of hours.
Anyway thanks for your help it works.
I'm currently having a problem, which seems to be related to closing a Form, while a scale, which is connected through a Serial Connection keeps sending data (about 3 packages per sek).
I handle new data over the DataReceived-Event (handling itself might be uninteresting for this issue, since I'm just matching data) Keep an eye on the COM_InUse variable and the allowFireDataReceived check.):
private void COMScale_DataReceived(object sender, EventArgs e)
{
if (allowFireDataReceived)
{
//set atomar state
COM_InUse = true;
//new scale:
if (Properties.Settings.Default.ScaleId == 1)
{
strLine = COMScale.ReadTo(((char)0x2).ToString());
//new scale:
Regex reg = new Regex(Constants.regexScale2);
Match m = reg.Match(strLine);
if (m.Success)
{
strGewicht = m.Groups[1].Value + m.Groups[2];
double dblComWeight;
double.TryParse(strGewicht, out dblComWeight);
dblScaleActiveWeight = dblComWeight / 10000;
//add comma separator and remove zeros
strGewicht = strGewicht.Substring(0, 1) + strGewicht.Substring(1, 2).TrimStart('0') + strGewicht.Substring(3);
strGewicht = strGewicht.Insert(strGewicht.Length - 4, ",");
//write to textbox
ThreadSafeSetActiveScaleText(strGewicht);
COMScale.DiscardInBuffer();
//MessageBox.Show(dblScaleActiveWeight.ToString(), "dblScaleActiveWeight");
}
}
//free atomar state
COM_InUse = false;
}
}
The COM_InUse variable is a global bool and "tells" if there is a current process of handling data.
The allowFireDataReceived is also a global bool and if set to false will lead to no extra handling of the data which has been sended.
My problem now is the following:
It seems that Eventhandling is a separate Thread, which leads to a deadlock on klicking the Cancel-Button since the COM_InUse will never turn to false, even if the Event was handled (see end of COMScale_DataReceived, where COM_InUse is set to false).
While setting allowFireDataReceived = false works perfectly (no handling any more), as I said: the while loop will not terminate.
private void bScaleCancel_Click(object sender, EventArgs e)
{
allowFireDataReceived = false;
while (COM_InUse)
{
;
}
if (!COM_InUse)
{
ret = 1;
SaveClose();
}
}
When I comment out the while-block I have to click twice on the button, but it works without a crash. Since this very user unfriendly, I'm searching for an alternative way to safely close the window.
Info:
Simply closing (without checking if the COM-Data was processed) lead to a fatal crash.
So, maybe someone can explain to me what exactly causes this problem or can provide a solution to this. (Maybe one would be to trigger the Cancel-Clicking Event again, but that is very ugly)
Greetings!
I count on you :)
//edit:
Here is the current code of
private void ThreadSafeSetActiveScaleText(string text)
{
// InvokeRequired required compares the thread ID of the
// calling thread to the thread ID of the creating thread.
// If these threads are different, it returns true.
if (this.lScaleActive.InvokeRequired)
{
SafeActiveScaleTextCallback d = new SafeActiveScaleTextCallback(ThreadSafeSetActiveScaleText);
this.Invoke(d, new object[] { text });
}
else
{
this.lScaleActive.Text = text;
}
}
ThreadSafeSetActiveScaleText(strGewicht);
Yes, the DataReceived event runs on a threadpool thread. You already knew that, you wouldn't have called it "ThreadSafe" otherwise. What we can't see is what is inside this method. But given the outcome, it is highly likely that you are using Control.Invoke().
Which is going to cause deadlock when you loop on COM_InUse in code that runs on the UI thread. The Control.Invoke() method can only complete when the UI thread has executed the delegate target method. But the UI thread can only do that when it is idle, pumping the message loop and waiting for Windows messages. And invoke requests. It cannot do this while it looping inside the Click event handler. So Invoke() cannot complete. Which leaves the COM_InUse variable for ever set to true. Which leaves the Click event handler forever looping. Deadlock city.
The exact same problem occurs when you call the SerialPort.Close() method, the port can only be closed when all events have been processed.
You will need to fix this by using Control.BeginInvoke() instead. Make sure the data is still valid by the time the delegate target starts executing. Pass it as an argument for example, copying if necessary.
Closing the form while the scale is unrelentingly sending data is in general a problem. You'll get an exception when you invoke on a disposed form. To fix this, you'll need to implement the FormClosing event handler and set e.Cancel to true. And unsubscribe the DataReceived event and start a timer. Make the Interval a couple of seconds. When the timer Ticks, you can close the form again, now being sure that all data was drained and no more invokes can occur.
Also note that calling DiscardInBuffer() is only good to randomly lose data.
Using Microsoft's EWS, we're able to listen to a mailbox and take actions when a new email comes in. However, I can't figure out how to avoid the connection timing out.
Per Microsoft, here is the constructor for a StreamingSubscriptionConnection:
public StreamingSubscriptionConnection (
ExchangeService service,
int lifetime
)
In my app, I've coded it as follows:
service = new ExchangeService(ExchangeVersion.Exchange2010_SP1);
StreamingSubscriptionConnection conn = new StreamingSubscriptionConnection(service, 30);
In other words, I've got the timeout (lifetime) set to 30 minutes, because that's the highest I've been able to set it. How can I increase this? Or, how can I trick this subscription into staying alive, even if ~45 minutes transpire between incoming emails?
30 minutes is a hard limit. You can not change it to a higher value.
To solve this issue, wire up a handler to the OnDisconnected handler of the OnDisconnect event of the connection instance. Restart the subscription from there (just call connection.Open() from that handler).
If anyone else is interested, this is how I am accomplishing this.
I want to keep the connection open, so I am resetting it in the OnDisconnect handler.
However, before resetting it, I check the private "subscriptions" dictionary on the connection object using reflection.
This allows me to unsubscribe from my connections elsewhere in my code (OnNotificationEvent), and when all subscriptions have been unsubscribed from, I am then able to close the connection.
Here is my Code:
void connection_OnDisconnect(object sender, SubscriptionErrorEventArgs args)
{
var c = (Dictionary<string, StreamingSubscription>)typeof(StreamingSubscriptionConnection).GetField("subscriptions",System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).GetValue(sender);
if (c.Count > 0)
{
// reopen the connection
((StreamingSubscriptionConnection)sender).Open();
using (var db = new Metrics_DatabaseEntities())
{
PushNotificationTest pt = new PushNotificationTest();
pt.RetObj = "Connection reset";
db.PushNotificationTests.Add(pt);
db.SaveChanges();
}
}
else
{
using (var db = new Metrics_DatabaseEntities())
{
PushNotificationTest pt = new PushNotificationTest();
pt.RetObj = "Connection closed!";
db.PushNotificationTests.Add(pt);
db.SaveChanges();
}
}
}
Please disregard the poor way that this is written, this is just my first version, as I plan to write this more cleanly soon. I just thought I would share my methodology with folks that might be interested.
If people are interested, here's the little bit of logic that got added.
I added this to my Start method:
conn.OnDisconnect +=
new StreamingSubscriptionConnection.SubscriptionErrorDelegate(OnDisconnect);
I then added the OnDisconnect method:
private void OnDisconnect(object sender, SubscriptionErrorEventArgs args)
{
Start();
}
Ultimately, this still needs improved, because this simply times-out and reconnects every half-hour, regardless of incoming email activity. I'd rather get something in place that resets the counter every time a new message comes in. Then, it would only time-out a couple times per day, instead of 48! Still, this is serving its purpose of keeping my email-listening program online.