|
You could disable the timer at the beginning of the event handler and then re-enable it at the end. That is if you don't mind the interval drifting a bit.
Public Sub TimerFired(ByVal sender As Object, ByVal e As System.Timers.ElapsedEventArgs)
myTimer.Enabled = False
' Do something...
myTimer.Enabled = True
End sub
Or you could block an interrupting event's entry by using a simple flag. An old school approach.
Private m_isBusy As Boolean = False
Public Sub TimerFired(ByVal sender As Object, ByVal e As System.Timers.ElapsedEventArgs)
If (m_isBusy) Then Return
m_isBusy = True
' Do something...
m_isBusy = False
End sub
|
|
|
|
|
thanks for the fast reply! i have tried the old school approached but it does not work, coz
Public Sub TimerFired(ByVal sender As Object, ByVal e As System.Timers.ElapsedEventArgs)
If (m_isBusy) Then Return
m_isBusy = True
' Do something...
m_isBusy = False <-------
End sub
i could not reach the code above and it is already interupted, and it end up without firing the TimerFired event anymore, and the 1st method works fine, thanks alot...
|
|
|
|
|
I'm surprised using a flag didn't work for you. As long as you check the flag at the top of the method and it doesn't ever return out before clearing the flag, it should work. Or perhaps an exception is being thrown and being caught somewhere else in the code? That would prevent the flag from getting cleared at the bottom too.
In any case, I'm glad you got your code working using the other method. If you're happy with it, then I am too.
|
|
|
|
|
hi,
i have another question, why is it the program still keep firing the TimerFired event, when i try stop the TimerFired event after caling myTimer.enabled?
|
|
|
|
|
elcheah wrote: why is it the program still keep firing the TimerFired event, when i try stop the TimerFired event after caling myTimer.enabled?
It shouldn't. If you disable the timer like this...
myTimer.Enabled = False
...then it shouldn't be calling that method anymore.
Perhaps your timer is being re-enabled elsewhere in your code?
Perhaps you have another timer being handled by that same method?
How are you setting up your timer anyways? The code you showed doesn't have a Handles keyword postfixed to the method, which tells me that you're not setting it up via WithEvents. Are you using AddHandler instead? Or a delegate?
|
|
|
|
|
ya, i am using AddHandler in Page_load,
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load<br />
<br />
AddHandler myTimer.Elapsed, AddressOf TimerFired<br />
<br />
End sub<br />
<br />
Public Sub TimerFired(ByVal sender As Object, ByVal e As System.Timers.ElapsedEventArgs)<br />
' My_code<br />
End sub
then i control the timer with 2 buttons (start,stop) by using MyTimer.Enabled = True,MyTimer.Enabled = False. Is that a wrong way of coding?
|
|
|
|
|
Now we're getting somewhere. :->
I see a few possible issues here.
(1)
You need a RemoveHandler for every AddHandler that you have. If you don't call RemoveHandler, then your timer will continue to persist in memory, even after your form has been closed. This is because a reference is still being kept alive by the AddHandler function.
The best place to call RemoveHandler is in your form's Closed event handler.
However, an even easier solution is to use a timer control on your form instead, via the designer. The designer will automatically declare the timer member with the "WithEvents" keyword, which automatically hooks up event handlers for you at compile time. When you select its Tick event from the IDE's drop down box, it'll insert that method postfixed with the "Handles" keyword.
(2)
Watch out when using the System.Timers.Timer class. By default, this timer operates on another thread which can cause race conditions when used on a form. You can avoid this issue by synching the timer to your UI's thread. However, an even easier solution is to use System.Windows.Forms.Timer instead, which is a control that's selectable in the UI designer, under the Form section.
(3)
You shouldn't use Timer.Enabled to block access to the TimerFired() method if you're controlling the timer enable from the Form too. This could put the timer in a bad state. Instead you should use a flag like I stated before, which should work once you fix the above issues.
|
|
|
|
|
hi, i have trouble with the 1st issue u mentioned, can you show me a simple piece of code on how it is done? i have tried but counldn't get it done Thank you very very much ...
|
|
|
|
|
You need to handle the Form Closed event. The IDE will automatically create this method for you by going to the form source code, select (Form Events) from the top left combo box, and then select Closed from the top right combo box.
Then you can remove the event handler as follows...
RemoveHandler myTimer.Elapsed, AddressOf TimerFired
Notice how it looks similar to your AddHandler. All you have to do is copy your AddHandler line and replace Add with Remove. It's important that the object reference and the method address exactly match the AddHandlers parameters.
|
|
|
|
|
at last i got it,you really helped me alot! thanks for the explanation and guidance, thank you very much!
|
|
|
|
|
Hi everybody,
I have to use an API for a CAN board that only exist in C langage. and I've got a problem with a C function that use a void* parameter.
in VB6 I used the any type but it doesn't exist in .net
so I found example on MSDN that use < MarshalAs( UnmanagedType.AsAny )> ByVal Myparam to replace any
it works fine to pass data to the function but it doesn't work to get data form the function
Does somebody already do that?
Thanks for your help
JP
|
|
|
|
|
If the function uses the pointer to return data, the pointer has to point to a structure that is large enough to hold the data that the function writes to it.
You also have to know how the data is structured to read it.
---
b { font-weight: normal; }
|
|
|
|
|
Thank you for your answer,
I did some test whith a simple C function and I succeed to localize the problem (but not the solution...)
the stuct I used is the following in C :
typedef struct{
int valint;
double valdouble;
char ValString[8];
}t_TestData;
When I call the function in VB I déclare the strcuture like that :
Public Structure t_TestData
Dim valint As Integer
Dim valdouble As Double
<vbfixedarray(8)> Dim Data() As Char
Public Sub Initialize()
ReDim Data(8)
End Sub
End Structure
valint and valdouble are updated correctly but not the Array Data
I call Initialize before calling the C function and I tried with the folowing declarations
Declare Sub TestDll Lib "TestvoidParam.dll" (ByVal t As Integer, ByRef TestData As t_TestData)
or
Declare Sub TestDll Lib "TestvoidParam.dll" (ByVal t As Integer, <marshalas(unmanagedtype.asany)> ByVal TestData As Object)
but it doesn't work, I've got an unknown exception. So the problem is to Get the Data of a fix size array of a structure.
have you got an idea?
Thanks
JP
If the structure is without
|
|
|
|
|
There are no fixed size arrays in .NET. Your Data member is a reference to an array object, and the ReDim statement is really:
Data = New Char(8)
If the C structure contains the array as a value type, the structure contains the character data itself, not a reference.
Test if declaring characters as value types in the structire gets you any closer:
Dim Data0 as Char
Dim Data1 as Char
Dim Data2 as Char
Dim Data3 as Char
Dim Data4 as Char
Dim Data5 as Char
Dim Data6 as Char
Dim Data7 as Char
Another thing that might cause you problem is if the char datatype is not a unicode character as in .NET. Then you have to declare the data as bytes and convert it to characters.
---
b { font-weight: normal; }
|
|
|
|
|
Thank you very much for your help,
it works when I declare 8 char Data (the C char is also unicode character).
I've got a C structure with an array of 256 char so I have to declare 256 Char in my VB struct!!!
Not very smart
thanks again
JP
|
|
|
|
|
Perhaps the MarshalAs[^] attribute can be used for this.
---
b { font-weight: normal; }
|
|
|
|
|
I found the solution ,
my structure is define like that in vb
Public Structure t_TestData
Dim valint As Integer
Dim valdouble As Double
<marshalas(unmanagedtype.byvalarray, sizeconst:="9)"> Dim Data() As Char
End Structure
And it works
Thanks for your help
JP
|
|
|
|
|
oops I did a mistake when I post the message (forget to check ignore HTML....)
the structure is
Public Structure t_TestData
Dim valint As Integer
Dim valdouble As Double
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=9)> Dim Data() As Char
End Structure
|
|
|
|
|
I want open mycomputer,control panel,Accessories and other windows components through VB.net.
Please help me.
|
|
|
|
|
You're going to have to be more specific about this. Each of these would require its own method to open. Some of which might not result in what you were expecting.
What exactly do you mean by "open"? What are you trying to do with this functionality?
RageInTheMachine9532
"...a pungent, ghastly, stinky piece of cheese!" -- The Roaming Gnome
-- modified at 10:13 Wednesday 18th January, 2006
|
|
|
|
|
I have a client who wants a Windows Form with about 5 large datagrids on it. Since some of these may not be applicable to the current user we want to be able to make each datagrid collapsable/expandable so that just the header row is visible. How could I go about inserting a custom icon (a "+" and "-" which would interchange depending on the current collapsed state - as in Explorer or the TreeView control) on the DataGrid header row?
I've googled this but can't find anything similiar - I've also got a tight deadline so am hoping someone can point me in the right direction!
TIA...
Mike
|
|
|
|
|
If they're not applicable to the current user, why show them at all? It goes against standard practices.
There's no built in support for this in the DataGrid control. You'd have to create your own DataGrid control, inheriting from DataGrid, and providing the properties and code to ownerdraw the headers yourself. You might want to Google for "ownerdraw datagrid" for something similar before attempting to tackle this. Your deadline might prevent you from implementing it.
RageInTheMachine9532
"...a pungent, ghastly, stinky piece of cheese!" -- The Roaming Gnome
|
|
|
|
|
Thanks Dave... that's what I suspected.
Since we don't have time to an "ownerdraw" solution what I've ended up doing is dynamically creating a button control and adding a click event for it which sets the DataGrid.Height property as required. The button is created Ok but the problem I'm having now is that it does not display over the top left hand corner of the DataGrid as I need it to - it's actually getting positioned in the right location but *under* the datagrid... how do I force the new button to display over the top of the DataGrid (ie: at position 0,0 in the caption)? Is there some sort of z-index as there is in HTML forms? (See the code below to see what I'm doing.)
Also, I want to be able to make the scrollbars in the grid non-visible when it collapses then re-show them when it expands - I guess it's the same problem where I'd need to draw/hide the scrollabrs myself by overriding the appropriate method or event in the DataGrid control - any thoughts on this? I don't believe there is any access to DataGrid scrollbars except via a custom DataGrid control but if you (or anyone else) knows how to do this I'd be grateful!
Cheers,
Mike
<br />
...<br />
'NB: dg1 is my DataGrid<br />
dg1.DataSource = _dataSet.Tables("customers")<br />
dg1.CaptionText = " Customers" 'Allow room for the collapse/expand button in the caption row.<br />
<br />
'Now add the expand/collapse button dynamically over the left hadn top corner of the DataGrid.<br />
Dim btnCollapse As New Button<br />
btnCollapse.Height = 20<br />
btnCollapse.Width = 20<br />
btnCollapse.FlatStyle = FlatStyle.Flat<br />
btnCollapse.Top = dg1.Top<br />
btnCollapse.Left = dg1.Left<br />
btnCollapse.Text = "-"<br />
btnCollapse.BackColor = Color.AliceBlue<br />
btnCollapse.ForeColor = Color.Navy<br />
btnCollapse.Name = "btnCollapse"<br />
btnCollapse.TabIndex = dg1.TabIndex + 1<br />
AddHandler btnCollapse.Click, AddressOf Me.btnCollapse_Click<br />
Me.Controls.Add(btnCollapse)<br />
...<br />
End Sub
|
|
|
|
|
You could try calling the button's .BringToFront method to get the control to appear on top of the DataGrid. There may be some pitfalls to doing this, like the DataGrid overpainting the button anyway, but that's about the best method you've got right now.
RageInTheMachine9532
"...a pungent, ghastly, stinky piece of cheese!" -- The Roaming Gnome
|
|
|
|
|
Thanks again Dave... I've got it working on a Form with a DataGrid dragged onto it. I now need to make a custom control (which inherits from DataGrid) but has the same ability to add the expand/collapse button dynamically. However, I can't work out which Method or Event I need to override and add the new button code to... I tried it in OnControlCreated and OnPaint (first calling each's respective MyBase method) but it just gets ignored... any advice on where I'd put something like this?
Sorry to be a pain - it's very difficult to work out where to put this stuff with all the events and methods supported by .Net controls!
Cheers,
Mike
|
|
|
|