I have a function which does some tasks in database trough a function contained in a dll. That function need to be executed many times with different parameters, but sometimes it takes too much time and need to kill the process and continue with the queue. The function in de dll doesn't have any timeout option, so I tried to control this creating a thread. I'm not used to work with threads, but after some research I made something like this code:
Dim Thread As New Threading.Thread(AddressOf Function)
Thread.Start()
Thread.Join(maxTime)
If(Thread.IsAlive) Then
WriteLogFile("Error [....]")
Thread.Abort()
End If
Probabily it isn't the smartier or most elegant way to do it, but it seemed to work when I tested it, but now I see that the "timeout" doesn't work. Well, it seems to work well if I set the timeout with a few seconds. But if I set it to 10 minutes, which is what I need, takes much more time than 10 minutes. I can expect that maybe Thread.join() is not totally accurate, but the difference is not jsut few seconds.
I tried many similar ways, so i don't know if i have the right focus of the problem. Maybe the malfunction of the code comes from the way of work of the .dll function, but first I need to discard the posibility of a mistake from myself (which i think is more probabily).
¿Can anyone tell me where is the mistake, or another way of doing this safer?
Thanks in advance.
Answered from comment of Hans. In order to control the execution of unmanaged code, threads can't provide a proper handling to finalize the function, so to implement a true timeout limiter, is needed to launch that function inside other project called as a process, to be able to call Kill() function, which really stops the process.
Related
I'm not sure if this is possible or not, and I'm afraid I have no code at the moment, but I'm working on it. I've been searching for techniques like what I'm trying to do, but I'm not sure if anything is out there... let me explain conceptualy what I'm trying to do...
I have a small multi-threaded VB.net application I'm writing. In this application I'm using a com object. Initially I was trying to share this object between multiple threads - no dice. It was breaking on a wait for event line, which was when I learned about message pumping... Which I'm not sure I'm up to.
So, what I would like to try to do is set up a thread with that object and keep it running in a loop waiting for input from one of the other threads. When it gets such input, I'd like it to use the com object to perform a few tasks and then update a private class level collection, and then return to looping until I kill it.
I've been looking around to see if any sort of functionality like this is described anywhere, but I'm coming up dry. I'd most likely be creating this thread as a task... here's sort of what I'm thinking the first part would look like...
Dim openCheckTask As Task
openCheckTask = Task.Factory.StartNew(Sub() openOrderCheck())
...
Sub openOrderCheck()
Dim myComObject As ComObject = New ComObject
Do
Wait for input '<- ? This sort of plays into what I'm looking for...
myComObject.doSomeStuff
SomeCollection.Add(someValue)
Loop
End Sub
I really have no idea how to proceed from there. It's also worth noting that this thread would need to have a cue of commands, it could be executing one and have another or more waiting to be executed... not sure if that is possible either.
Any hints or suggestions are appreciated! Thanks again for your time everyone.
Recently, this small, annoying, and random process from Yahoo, which I don't even use, has been starting randomly, and will begin taking up around 2000k memory. I have coded something I thought will automatically stop the process when it begins running, although it does not preform correct, nor does it do what I want it to do. This is what I have compiled:
Dim arrProcess() As Process = System.Diagnostics.Process.GetProcessesByName("YahooUIService")
Dim constant As Integer
While constant = 5 'This is in the form
For Each p As Process In arrProcess
p.Kill()
Next
End While
Does anyone know what I am doing wrong, and how I can correct myself? I know VB.NET well, although yes, there are many small things like this that throw me off.
Your code would only detect the app if it was open at the time your app started. To continuously detect the app you'd have to call GetProcessesByName() INSIDE your While loop. Definitely put some kind of delay in there, though, as otherwise you'll ramp up CPU usage to 100%. It'd be better to use a Timer() control and check for the process in the Tick() event.
VB.NET, .NET 4
Hello all,
I have an application that controls an industrial system. It has a GUI which, once a process is started, principally displays the states of various attached devices. It basically works like this:
A System.Timers.Timer object is always running. At each Elapsed event, it polls the devices for their current values and invokes controls on the GUI, updating them with the new values.
A start button is clicked, a process time Stopwatch object is created and started (Labels on the GUI are now invoked and updated on the System.Timers.Timer's Elapsed event, in addition to the other work that is taken care of on this event)
A new thread is created which runs a Process() subroutine
Some Stopwatch objects are created and started (these Stopwatches are periodically restarted during the process via their Restart() method.
Some logic is executed on the new Stopwatchs' Elapsedmilliseconds properties to determine when to do things like write new setpoints to the devices, update the data log, etc...
Here's my problem: The program occasionally freezes. My ignorant efforts at tracking down the problem have led me to suspect that read/writes to the subset of devices that are RS-232 controlled are the culprits most of the time. However, I occasionally see other strange things upon program freeze, e.g., one of the time Labels whose Text property is determined by a Stopwatch's Elapsedmilliseconds property sometimes will show an impossible value (e.g., -50 hours or something).
For the RS-232 problems, I suspect something like a read event is being executed at the same time as a write event and this causes a freeze(?). I tried to prevent this by making sure that all communication with an RS-232 device is funneled through a Transmit() subroutine which has the following attribute:
Which, as far as my ignorance permits me to understand, should force one Transmit() execution to finish completely before another one can start. Perhaps another risk is the code getting blocked here if one Transmit() never finishes?
Regarding the Stopwatch trouble, I speculate that the problem is that the Timer is trying to update a GUI Label at the same time that the Stopwatch's Restart() method is being executed. I'm unsure if this could cause a problem. All I know is that this problem has only occurred at a point in the process when a Restart() call would be made.
I am wondering if I could use a SyncLock or something to lock a Stopwatch while the Label is being updated (or, conversely, while its being restarted)? Or, perhaps I should stop the Timer, restart the Stopwatch, and then start the timer again, like so?:
Timer.Stop
Stopwatch.Restart
Timer.Start
My trepidation regarding how to proceed is due to my complete lack of understanding of how .NET synchronization objects actually work. I've tried slapping a few SyncLocks in various places, but I really have no idea if they're implemented correctly or not. I'm wondering if, having provided all this context, someone really smart might be able to tell me how I'm stupid and how to do this right. I would really appreciate any input. If it would be useful to provide some code snippets, I'd be happy to, I just worry that everything's so convoluted that it would just detract from what I'm hoping is a conceptual question.
Thanks in advance!
Brian
I would consider a shift to a task scheduling framework instead of relying on manual manipulation of timers if your working on anything SCADA related. A simple starting point would be something similar to the hardcodet.Scheduling classes and you can move to something like the beast that is Quartz. Most of these types of frameworks will provide you with a way to pause and resume scheduled actions.
If I'm working with Modbus, I normally keep a local cache of the register values and make changes to any value fire a change event. This has the benefit of allowing you to implement things like refreshing values manually without interfering with your process scheduling and checking for deadband when evaluating your polled response. This happened to be the side effect of implementing a polled protocol to a subset of the OPC DA interface.
I am running a test program for VB.NET, and it will simply crunch a million numbers in for loop. I've linked a variable implying the progress of the for loop with the progress bar, but it seems that when I run the program, the progress bar does not update itself. The bar itself has only value 0-100 as input (as stated in the document) and I've tested it without using the for loop, and it works.
I think this has to do with threads, but I am not sure how things work in VB.NET exactly yet. So I want to seek an advice from an expert first.
Any advice is appreciated.
Don't know if this still applies for .net (or if this is a VB6 question), but Application.DoEvents was generally the solution in VB6 days.
Try Application.DoEvents inside your loop that updates the progress bar.
long time ago but i think you need the
DoEvents
statement
I have an Excel macro that takes an exceedingly long time. It seems to crash Excel (I get a Not Responding message in the taskbar) when I leave it unattended, but if I put a breakpoint that gets hit every five or ten seconds, it's OK. Trouble is, I'll need to step on from the breakpoint about a quarter of a million times (we're looking at about 200 hours to execute this beast)
I'm guessing that the absence of message pump activity is antagonising the kernel, so how might I flush the message queue? Or am I barking up the wrong tree entirely?
I'm very new to this, by the way, so documentation references will be very welcome.
Cheers,
Guy
Seconding the opinion that 200h is a bit worrying, however you can try the DoEvents statement which "surrenders execution of the macro so that the operating system can process other events". (Note that calling DoEvents has an additional time penalty)
I have to agree with 0xA3, if you have an excel routine that is expected to take over 200 hours to run then you're either setting it up in a very inefficient manner or you're using the wrong tool for this job.
In any case, there are a few things you can do to optimize the routine. These will be especially helpful if you are constantly writing values to individual cells.
Sub MarathonCalc
Application.EnableEvents = False
Application.ScreenUpdating = False
' Code to decode human genome goes here
Application.EnableEvents = True
Application.ScreenUpdating = True
End Sub
Again, if you post some of your code perhaps we can help track down why it's taking so long.
"Not responding" doesn't mean that Excel is crashing, it simply means that it does not actually respond to window messages.
Unless that is a problem there is nothing you need to worry about. I'm rather worried about your comment that you expect the task to take 200h (which is more than a week!). It seems to me that you are not using the right tool for this job. Try to find out what is taking so long and explain what you are actually doing. Then we can see how to better solve this task.
The previous answers have given you 'DoEvents' and that's the first-line fix for your problem.
However... A closer look at what's happening raises some worrying questions. Firstly, Excel's threading model is rather primitive: there's one process (according to the documentation) and no new threads are created by internally- or externally-generated events, callbacks and messages. One process, and one process ONLY, and everything else has to wait until the current VBA macro or spreadsheet calculation runs to completion.
Actually, some things can interrupt this: {esc} and {ctrl-break} (although these can be temporarily disabled), so there's at least one other thread running in Excel all the time, and you'd EXPECT the operating system to be allowed to break into a process... Wouldn't you?
The ugly reality is that the Excel application does not allow external events and messages to run to an 'event sink' while a macro or calculation is running, unless you call 'DoEvents' and some Windows Messages (note the capitalisation) still won't be dealt with.
If an undocumented number of messages and external events are left hanging around, the application will crash. Based on my own tests, I think the number is 50; there's documentation about a registry setting out there, but I'm not linking to material that I consider unreliable - I've tried the setting in question and found it to be ineffective.
So where does that leave you?
Firstly, look at your code again. Application.EnableEvents = False and Application.ScreenUpdating = False are useful settings: your next step is to find all and every read- or write operation to individual cells on the sheet and just grab arrays of cells - it's much faster to grab an array using myVBAarray=Range.Value, do your calculations in VBA, and write the VBA array variant back to Range.Value.
Secondly... You've also seen that the 'wait' state imposed by a breakpoint allows some things to sort themselves out. That sounds like an external process (a database query?) running asynchronously: could it be that the message or event which is crashing Excel is coming from that very process?