473,287 Members | 1,574 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,287 software developers and data experts.

Threading(?) & FileSystemWatcher

Hi,

I am trying to use FileSystemWatcher to watch a log file which is
written to via a 3rd party app and display the log in listbox on a
form. The FileSystemWatch seems to work okay but I get the following
error when I try to write to the listbox:

"A first chance exception of type 'System.ArgumentNullException'
occurred in System.Windows.Forms.dll"
>From my search so far it seems this may be to do with the watcher
being in a different thread but to be honest I haven't really figured
the ins and outs of threading. This was meant to be a nice simple
project to learn from so I'd really appreciate any tips.

My form has a run button which calls the following routine (in a
separate module):

Private mstrPathToWatch As String
Private mstrFileToWatch As String
Private mfswWatchFolder As FileSystemWatcher
Private frm As frmMain

Public Sub StartFileWatch(ByVal frmLogForm As frmMain)

mfswWatchFolder = New FileSystemWatcher
mfswWatchFolder.SynchronizingObject = frmLogForm.lbxRunLog
'this was just a guess but I don't understand it and it
doesn't seem to help

'Create module level reference to form so can access it from
changed event
frm = frmLogForm

'Specify the path we want to watch
mstrPathToWatch = "C:\Documents and Settings\Andrew\My
Documents\TEMP"
mstrFileToWatch = "demo.txt"
mfswWatchFolder.Path = mstrPathToWatch
mfswWatchFolder.Filter = mstrFileToWatch

'Add a list of Filter we want to specify
mfswWatchFolder.NotifyFilter = IO.NotifyFilters.DirectoryName
mfswWatchFolder.NotifyFilter = mfswWatchFolder.NotifyFilter Or
IO.NotifyFilters.FileName
mfswWatchFolder.NotifyFilter = mfswWatchFolder.NotifyFilter Or
IO.NotifyFilters.Attributes

'Add a handler for each event (in this case just file change)
AddHandler mfswWatchFolder.Changed, AddressOf FileHasChanged

'Set this property to true to start watching
mfswWatchFolder.EnableRaisingEvents = True

End Sub

The 'FileHasChanged' event created above reads the log file
(successfully) and then calls a sub back on the form which writes the
array to the listbox.

Thanks a lot!

Andrew

May 2 '07 #1
4 4361
Hi hooksie,
I think perhaps the most important piece of code you didn't post there was
how you are writing to the list on the form from the thread and what
parameters you are sending through. You should ideally be "invoking" any
methods on the form, rather than just calling sub-routines on it from your
thread.
Robin
May 2 '07 #2
Thanks for the reply.

I write each line of the log to an array and then pass to the sub
which is in the form as follows:

frm.LogMsg(astrLines)

The form code looks like:

Public Sub LogMsg(ByVal astrLogText() As String)
lbxRunLog.BeginUpdate()
lbxRunLog.Items.AddRange(astrLogText)
'Make sure the bottom entry is visible
lbxRunLog.TopIndex = lbxRunLog.Items.Count - 1
lbxRunLog.EndUpdate()
Me.lbxRunLog.Refresh()
End Sub

I'm interested to hear what you mean by "invoking" - thanks for taking
the time to look at this.

Andrew

On May 2, 10:39 pm, "Robin Tucker" <rtgro...@hotmail.co.ukwrote:
Hi hooksie,

I think perhaps the most important piece of code you didn't post there was
how you are writing to the list on the form from the thread and what
parameters you are sending through. You should ideally be "invoking" any
methods on the form, rather than just calling sub-routines on it from your
thread.

Robin

May 2 '07 #3

Hi,

Looking at your code, I have to assume astrLogText = nothing when it enters
the procedure in order to throw that exception, so put a break-point and
check its value before AddRange. Secondly, accessing and manipulating
windows controls from a thread other than the main process thread is fraught
with problems. Because you don't know what the main process thread is doing
at the time, its possible to get race, lock and other such synchronisation
errors. "Invoke" (BeginInvoke, EndInvoke, Invoke) allow you to call a
method on a windows form or control from a thread other than the thread they
were created on. I think under the hood the CLR uses the controls message
pump to ensure the methods are called in an orderly manner. Use Google to
find out more or look in the MSDN literature. Your keywords are:
Invoke+VB.NET :).

There are many examples around of using Invoke. My preference is to create
a method on the main form, in this case called LogMsg and then invoke that
method from your thread using a delegate. The invoke procedure would look
something like this:
' Declare a delegate

Private Delegate Sub _LogMsgDelegate(astrLogText() as String)

' Method to invoke the LogMsg method on the main form.

Public Sub InvokeLogMsg(ByVal astrLogText() as String)

Dim Parameters(0) As Object

Parameters(0) = astrLogText

' If the invoke fails, it's usually because the form has been
' destroyed. The window handle of the form or control must
' be valid for the invocation to succeed. An unhandled exception
' on a form or in a control will cause .NET to dispose of it,
' resulting in any running thread failing when it invokes.

Try

frm.Invoke(New LogMsgDelegate(AddressOf frm.LogMsg), Parameters)

Catch ex As Exception

...

End Try

End Sub

and on your form......

Public Sub LogMsg(ByVal astrLogText() As String)

lbxRunLog.BeginUpdate()
lbxRunLog.Items.AddRange(astrLogText)

' Make sure the bottom entry is visible

lbxRunLog.TopIndex = lbxRunLog.Items.Count - 1
lbxRunLog.EndUpdate()

Me.lbxRunLog.Invalidate ()

End Sub

Sorry I didn't test it, but cut and messed around with some code from one of
my projects. Hope this is useful.

Robin

I write each line of the log to an array and then pass to the sub
which is in the form as follows:

frm.LogMsg(astrLines)

The form code looks like:

Public Sub LogMsg(ByVal astrLogText() As String)
lbxRunLog.BeginUpdate()
lbxRunLog.Items.AddRange(astrLogText)
'Make sure the bottom entry is visible
lbxRunLog.TopIndex = lbxRunLog.Items.Count - 1
lbxRunLog.EndUpdate()
Me.lbxRunLog.Refresh()
End Sub

I'm interested to hear what you mean by "invoking" - thanks for taking
the time to look at this.

Andrew

On May 2, 10:39 pm, "Robin Tucker" <rtgro...@hotmail.co.ukwrote:
>Hi hooksie,

I think perhaps the most important piece of code you didn't post there
was
how you are writing to the list on the form from the thread and what
parameters you are sending through. You should ideally be "invoking" any
methods on the form, rather than just calling sub-routines on it from
your
thread.

Robin


May 2 '07 #4
You solved it! My apparent problem turned out to be something simpler
than I had assumed. The last value in my array was nothing and this
was actually what was causing the error.

I'm still struggling with the concepts around Invoke (web resources so
far a bit over my head) but I'll keep trying and have implemented your
suggestion anyway - at a high level I can understand how this could
cause a problem otherwise.

Thanks for your help.

Andrew

On May 3, 12:24 am, "Robin Tucker" <rtgro...@removehotmail.comwrote:
Hi,

Looking at your code, I have to assume astrLogText = nothing when it enters
the procedure in order to throw that exception, so put a break-point and
check its value before AddRange. Secondly, accessing and manipulating
windows controls from a thread other than the main process thread is fraught
with problems. Because you don't know what the main process thread is doing
at the time, its possible to get race, lock and other such synchronisation
errors. "Invoke" (BeginInvoke, EndInvoke, Invoke) allow you to call a
method on a windows form or control from a thread other than the thread they
were created on. I think under the hood the CLR uses the controls message
pump to ensure the methods are called in an orderly manner. Use Google to
find out more or look in the MSDN literature. Your keywords are:
Invoke+VB.NET :).

There are many examples around of using Invoke. My preference is to create
a method on the main form, in this case called LogMsg and then invoke that
method from your thread using a delegate. The invoke procedure would look
something like this:

' Declare a delegate

Private Delegate Sub _LogMsgDelegate(astrLogText() as String)

' Method to invoke the LogMsg method on the main form.

Public Sub InvokeLogMsg(ByVal astrLogText() as String)

Dim Parameters(0) As Object

Parameters(0) = astrLogText

' If the invoke fails, it's usually because the form has been
' destroyed. The window handle of the form or control must
' be valid for the invocation to succeed. An unhandled exception
' on a form or in a control will cause .NET to dispose of it,
' resulting in any running thread failing when it invokes.

Try

frm.Invoke(New LogMsgDelegate(AddressOf frm.LogMsg), Parameters)

Catch ex As Exception

...

End Try

End Sub

and on your form......

Public Sub LogMsg(ByVal astrLogText() As String)

lbxRunLog.BeginUpdate()
lbxRunLog.Items.AddRange(astrLogText)

' Make sure the bottom entry is visible

lbxRunLog.TopIndex = lbxRunLog.Items.Count - 1
lbxRunLog.EndUpdate()

Me.lbxRunLog.Invalidate ()

End Sub

Sorry I didn't test it, but cut and messed around with some code from one of
my projects. Hope this is useful.

Robin
I write each line of the log to an array and then pass to the sub
which is in the form as follows:
frm.LogMsg(astrLines)
The form code looks like:
Public Sub LogMsg(ByVal astrLogText() As String)
lbxRunLog.BeginUpdate()
lbxRunLog.Items.AddRange(astrLogText)
'Make sure the bottom entry is visible
lbxRunLog.TopIndex = lbxRunLog.Items.Count - 1
lbxRunLog.EndUpdate()
Me.lbxRunLog.Refresh()
End Sub
I'm interested to hear what you mean by "invoking" - thanks for taking
the time to look at this.
Andrew
On May 2, 10:39 pm, "Robin Tucker" <rtgro...@hotmail.co.ukwrote:
Hi hooksie,
I think perhaps the most important piece of code you didn't post there
was
how you are writing to the list on the form from the thread and what
parameters you are sending through. You should ideally be "invoking" any
methods on the form, rather than just calling sub-routines on it from
your
thread.
Robin- Hide quoted text -

- Show quoted text -

May 3 '07 #5

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
by: Rajesh Abraham | last post by:
I am looking to use Timers in my Windows Service application and just realised that apart from the forms Timer, there is also System.Threading,Timer and System.Timers.Timer. When should I prefer...
4
by: Ayende Rahien | last post by:
The following first throws the nasty exception dialog, and only then show me the message. Is there a way to avoid this? This occur both inside & outside VS. public class Test { private...
8
by: Z D | last post by:
Hello, I'm having a strange problem that is probably due to my lack of understanding of how threading & COM Interop works in a WinForms.NET application. Here's the situation: I have a 3rd...
1
by: Patrick | last post by:
I have an ASP.NET web service whose Web.Config is set to use impersonation <authentication mode="Windows" /> <identity impersonate="true" /> Within a Web Method, I want to use...
12
by: Aidal | last post by:
Hi NG. I'm creating a little app. that has to use a 3rd party API. The functions in this API has no return value but trigger events like OK or NOT OK with event args. Where I need to use this...
5
by: JasonX | last post by:
Im having problems with my program, in that if I close the main form while my new thread is doing work which involves writing to the main form, then I get an error about a disposed object. To...
2
by: Jeroen | last post by:
Hi all, I've been trying to get my head around threading. Here's an example from the book I'm reading: /***************************/ Mutex m = null; const string name = "xyz"; try
2
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 7 Feb 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:30 (7.30PM). In this month's session, the creator of the excellent VBE...
0
by: MeoLessi9 | last post by:
I have VirtualBox installed on Windows 11 and now I would like to install Kali on a virtual machine. However, on the official website, I see two options: "Installer images" and "Virtual machines"....
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: Aftab Ahmad | last post by:
Hello Experts! I have written a code in MS Access for a cmd called "WhatsApp Message" to open WhatsApp using that very code but the problem is that it gives a popup message everytime I clicked on...
0
by: Aftab Ahmad | last post by:
So, I have written a code for a cmd called "Send WhatsApp Message" to open and send WhatsApp messaage. The code is given below. Dim IE As Object Set IE =...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: marcoviolo | last post by:
Dear all, I would like to implement on my worksheet an vlookup dynamic , that consider a change of pivot excel via win32com, from an external excel (without open it) and save the new file into a...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.