Hello (again),
I'm trying to implement a filesystem watcher but have come unstuck with the parameters for my subscribed onChange method.
DEFINE VARIABLE FileSystemWatcher AS CLASS System.IO.FileSystemWatcher.
FileSystemWatcher = NEW System.IO.FileSystemWatcher("C:\MyDIRToWatch").
FileSystemWatcher:NotifyFilter = System.IO.NotifyFilters:LastWrite.
FileSystemWatcher:Filter = "*.*".
FileSystemWatcher:Changed:Subscribe(OnChange).
FileSystemWatcher:EnableRaisingEvents = TRUE.
METHOD PRIVATE FINAL VOID OnChange( Does anyone know what goes here? ):
RETURN.
END METHOD.
Could anyone point me in the right direction please. The code examples I've found have been in c# and not too helpful.
As always, thanks for the help :-)
Mark.
the docs say
object source, FileSystemEventArgs e
so I abl I would think
source as System.Object, e as FileSystemEventArgs
the docs say
object source, FileSystemEventArgs e
so I abl I would think
source as System.Object, e as FileSystemEventArgs
Thanks :-)
Yeah, I'd missed that. However, it's not possible to run this in OE as the filewatcher is multithreaded and OE is not. The code fires for the first file change but then hangs!
I did a little looking into this and it appears that a simple change to the code will make this OK to use in a single threaded environment like Progress.
Adding the line FileSystemWatcher:SynchronizingObject = this-object. will cause the methods used by the Change, delete etc. events to use the thread that started the form.
I've tested this in a form and with this line, no crashes occur. Without it, crashes are immediate.
Very little testing has been done, YMMV
Mhhh I tried this "Adding the line FileSystemWatcher:SynchronizingObject = this-object." but then I get a syntax-error "Incompatible data types in expression or assignment. (223)"
assign oFileSystemWatcher = new System.IO.FileSystemWatcher(p-NMpath, p-INfilter)
oFileSystemWatcher:NotifyFilter = System.IO.NotifyFilters:filename
oFileSystemWatcher:SynchronizingObject = this-object.
Has someone tried that solution with :SynchronizingObject = this-object.?
How can I make this work?
I also found some sollution to that 15740 error by using a helper-class but I do not understand how that works so ...
Regards
Didier
Have you tried casting THIS-OBJECT to System.ComponentModel.ISynchronizeInvoke?
e.g.
oFileSystemWatcher:SynchronizingObject = CAST(this-object,System.ComponentModel.ISynchronizeInvoke)
Right - what Ken said. But obviously, whatever THIS-OBJECT is, really has to be something that implements ISynchronizeInvoke, or the CAST will not work either.
Hi,
Again this is not completly clear to me.
I tried adding the oFileSystemWatcher:SynchronizingObject = cast(this-object, "System.ComponentModel.ISynchronizeInvoke").
Now I have no syntax-error but I get a run-time error (like Laura said)
Ongeldig cast van filesystemwatcher naar System.ComponentModel.ISynchronizeInvoke, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089. (12869)
When I then add the implement ISunchronizeInvoke (and all needed methods/properties) it compiles fine but when the program runs I still get the 15740 error (multi threaded and Progress single threaded.
So I guess this oFileSystemWatcher:SynchronizingObject doesn't work as expected/explained.
Isn't there someone that used the System.IO.FileSystemWatcher from a Progress process (or some other class that leads to that 15740 that error)?
How did you prevent that 15740 error:
You are trying to use a multi-threaded .NET object in a way that is not supported. The ABL cannot be called on a thread other than the main thread. (15740)
The ABL is single threaded. You will see this error if you use a .NET object that employs multiple threads and attempts to call back to the ABL on a thread other than the main processing thread.
Regards
Didier
In general, you cannot prevent error 15740. If the class sends events on other threads, it cannot be used from the ABL. It makes total sense that the class would be doing this as it is watching when changes are happening in the file system. Those changes can happen at any point, asynchronous to what is happening on the main thread.
But look at the SynchronizingObject property. I'm not sure I'm reading what it says correctly. But maybe that will help you.
In general, you cannot prevent error 15740. If the class sends events on other threads, it cannot be used from the ABL. It makes total sense that the class would be doing this as it is watching when changes are happening in the file system. Those changes can happen at any point, asynchronous to what is happening on the main thread.
But look at the SynchronizingObject property. I'm not sure I'm reading what it says correctly. But maybe that will help you.
Ok, it looks like this works ;-)
First i created a dummy System.Windows.Forms.Form object and assigned the SynchronizingObject with the handle of that Form-object.
Now the 15740 error does not arise and - it looks like - the events fire and are handled like I expected.
Still need some testing and not sure if there are some drawbacks by creating that dummy Form-object (I don't think so) but it looks promising
Thanks
:-)
You might be able to use System.Windows.Forms.Control instead of Form, as that is the base class that implements this interface.
Or you could try implementing the interface yourself, but I'm unsure that will be possible or work...
Yes i could but what are the benefits of using System.Windows.Forms.Control instead of Form,
As Brian alluded to, a class wrapper has the basic structure.
1. Define a Delegate for SomeMethodDelegate(SomeParemeter)
2. Public property of type Control (or any method to pass a form or widget)
3. Component that fires event on a different thread
4. Event Handler for Component's event
Inside call SomeMethod(SomeParameter)
5. SomeMethod(SomeParameter)
if form.InvokeRequired
form.Invoke(new SomeMethodDelegate(SomeMethod), new object[] { SomeParameter })
else
you can either call a public method of form passing SomeParameter or
you can raise a custom event passing SomeParameter (I prefer this approach)
NOTE: if you define a delegate with the same signature as Event Handler, you won't need a separate SomeMethod