|
Thanks Paulo,
Been reading up on threading a bit and still looking into using your solution.
Still have a few more questions...
while(!stopRequested)
{
manualResetEvent.WaitOne();
if (stopRequested)
break;
manualResetEvent.Reset();
lock(hashset)
{
foreach(var path in hashset)
{
... do what you need...
}
hashset.Clear();
}
}
... do what you need...
1) if it locks that hashset and then loops thru and processes
the files 1 by 1 (which could potentially take a couple minutes a file)
then wont the other threads need to sit and wait until they can obtain the lock on the hashset? For some reason to me that seems like it is defeating the purpose of using the extra thread that processes the files.
If the thread that processes the files is running and locks the hashset for 5 minutes say, and 5 more files get dropped into the IN directory causing 5 more filesystemwatcher.fileCreated events to happen, the 1st one will be waiting to obtain a lock on the hashset and the other 4 events will be waiting in line (and filling up the file system watcher buffer) won't they?
I was trying to avoid doing much work in the filesystemwatcher.fileCreated event (as many seem to suggests) to stop it from bottlenecking and filling it's buffer and cause events to get lost.
Maybe I'm missing something, but seems like if it sits there and waits for lock to become available, it could have just done the work itself.
Maybe I can alter the logic to lock hashset, get 1st file, unlock hashset, process the file, lock hashset, remove the file just processed from hashset , unlock hashset, loop again.
Does that make any sense or is this not a legit concern?
|
|
|
|
|
In this case, you are right.
So, I suggest you to make it different.
Create another object to be the "lock object".
private object hashsetLock = new object();
... and the thread code...
while(!stopRequested)
{
manualResetEvent.WaitOne();
if (stopRequested)
return;
HashSet<string> hashsetToProcess;
manualResetEvent.Reset();
lock(hashSetLock)
{
hashsetToProcess = hashset;
hashset = new HashSet<string>();
}
foreach(string item in hashsetToProcess)
... do what you need...
}
In this scenario, if you keep processing for 5 minutes, there is no problem, as the new hashset is no longer locked.
|
|
|
|
|
ok great,
I had a very similar idea of using a local copy, this is essentialy the same thing.
I'm going to try to implement the entire solution now.modified on Thursday, March 4, 2010 12:36 PM
|
|
|
|
|
Hey Paulo,
Sorry but just 1 last question / confirmation.
Been trying to wrap my head around the ManualResetEvent, it's new to me.
So in your code the file processing thread calls manualResetEvent.WaitOne();
to make it stop processsing and wait, then once a new file is added
(by either the file created event on the main thread or the folder
polling thread) it calls manualResetEvent.Set() in order to make
the file processing thread resume again? Is that correct.
Then the file processing thread calls manualResetEvent.Reset(); so that
next time through the loop it will stop again waiting for another thread
to signal it to resume again? Is that correct.
So the result is...the only thread that is being stopped is the file
processing thread which is preventing it from running when there are no
files to process.
Am I understanding this properly?
Thanks again!
|
|
|
|
|
Yes. The only thread that stops is the thread that calls the WaitOne.
But, one thread will stop by time (I suggested to use another ManualResetEvent, so you call otherManualResetEvent.WaitOne(60000) and you will wait or for the event to be set [at finalization] or for 60 seconds).
ManualResetEvent is one of the best sincronization objects 
|
|
|
|
|
Nice, thanks again!
I like it even more now that I fully understand it
I will use another ManualResetEvent instead of the Thread.Sleep
|
|
|
|
|
I have never used FileSystemWatcher (and I know very little about it) -- I always poll; mostly because I have been accessing files on remote systems, running who-knows-what operating system and I've never needed anything like near-real-time processing of new files; polling once an hour has been sufficient.
How I do that depends on the specifics of the situation.
The most general technique I use is to have a database table where I can define what files to seek:
Name Type1 Type2 Nullable Unique Read only
-------------- --------------- ---------------- -------- ------ ---------
KeyId System.Guid uniqueidentifier False False False
SearchIn System.String varchar(256) False False False
SearchFor System.String varchar(256) False False False
DeleteIt System.Boolean bit False False False
VersionsToKeep System.Byte tinyint False False False
LastSearch System.DateTime datetime True False False
SearchIn contains a directory to search -- e.g. \\someserver\someshare\path...
SearchFor contains a wildcarded filename -- e.g. *.csv
DeleteIt instructs the Service whether or not to delete the file once it has been processed
LastSearch contains the LastWriteTime of the newest file found, it is maintained by the Service
The Service uses a DirectoryInfo's GetFiles method to get a list of files and then checks each file's LastWriteTime to see if it is new and not currently being written to.
Many of you are now freaking out about the performance of this technique as the number of files in the directory grows, and you're correct, but when used in concert with a pro-active archiving and purging regimen this does not become a problem -- the real problem would be in allowing the number of files to grow unfettered in the first place.
|
|
|
|
|
John Simmons recently posted an excellent article about a new and improved way to use the File System Watcher. You should have a read about this[^] because John gives some great advice."WPF has many lovers. It's a veritable porn star!" - Josh Smith As Braveheart once said, "You can take our freedom but you'll never take our Hobnobs!" - Martin Hughes.
My blog | My articles | MoXAML PowerToys | Onyx
|
|
|
|
|
High praise indeed. Many thanks. .45 ACP - because shooting twice is just silly ----- "Why don't you tie a kerosene-soaked rag around your ankles so the ants won't climb up and eat your candy ass..." - Dale Earnhardt, 1997 ----- "The staggering layers of obscenity in your statement make it a work of art on so many levels." - J. Jystad, 2001
|
|
|
|
|
Hi,
I have to use this library in my C# program, but i am not able to add like a reference.
Do you know why?
Can i use it with DLLImport?How can I use the methods from this library?
Thanks,
Anca
|
|
|
|
|
In oreder to use the methods in the DLL you have to import it, add a reference to it.
What have you tried? Did you tried the right-click => Add Reference?
|
|
|
|
|
yes..and i am receiving an error: A reference to "C:\...\OUTLFLTR.DLL" could not be added.Please make sure that the file is accesible, and that it is a valid assembly or COM Component.
OUTLFLTR.DLL - is an outlook library.
Can you help me pls?
Anca
|
|
|
|
|
Yep. Well you need to DLL import it.
Something like:
[DllImport("myGroovy.dll")]
public static extern int GroveIt(string c);
[DllImport("myGroovy.dll")]
public static extern int UnGroveIt(int i);
But you need to know upfront the methods in the DLL. I have no ideea about the inner works
of the "OUTLFLTR.DLL" but MSDN should help, or Ging(Google+Bing).
|
|
|
|
|
Either it is a managed code DLL, then add a reference to it and use its classes as per the usual way;
or it is an unmanaged code DLL and you will need to use P/Invoke, which is hard for complex classes and structures.
Assuming it is Outlook related, I would guess it is unmanaged code.
Either way you need to know what functionality is inside and how to use it at the functional level; then figure out the API details. The normal way to do that is by getting and studying the documentation, which should come with the executable files.
|
|
|
|
|
DLLImport is the correct way.
Example:
[DllImport("your.dll", CharSet = CharSet.Unicode)]
static extern long YourFunction(long lParamValue, ...);
Take a look at this site (good reference for standard WinAPI dlls).Greetings
Covean
|
|
|
|
|
For example i have to use this function which contains also md5 decryption:
void ms_md5(
unsigned char* key,
unsigned char* data,
int length,
unsigned char *digest
)
{
MD5_CTX context;
MD5Init(&context);
MD5Update(&context,key,16);
MD5Update(&context,data,length);
MD5Final(digest, &context);
}
it's enough to
[DllImport("OUTLFLTR.DLL", CharSet = CharSet.Unicode)]
static extern void ms_md5(char* a,char* b,int l, char *d);
i am not sure how can i transmit the last parameter and after how i use in my program, like an usual procedure?
thanks a lot,
Anca
|
|
|
|
|
I would try this at first:
[DllImport("OUTLFLTR.DLL", CharSet = CharSet.Ansi)]
static extern void ms_md5(string a, string b,int l, string d);
But unsigned char* means that its not a const string (like const unsigned char*),
so MSDN says to use StringBuilder for marshalling like:
static extern void ms_md5(StringBuilder a, StringBuilder b,int l, StringBuilder d); Greetings
Covean
|
|
|
|
|
When i call the procedure i received this error message: an attempt was made to load a program with an incorrect format
The procedure has a key(the first parameter) and the documentation tell me that is 16-byte-long key.I think here is the problem.
I want that my procedure to return something like this, where the text to be more words: "63 anca black"
Entry # Word Weight Hash
2133 63 -0.009834 538bd1b2ab04f2d7205a3a9dd4010528
2133 anca -0.003434 539bd1b2ab04f2d7205a3a9dd4010528
2133 black -0.020834 540bd1b2ab04f2d7205a3a9dd4010528
Do you know also how can i use a structure from a .dll?
Thanks,
Anca
|
|
|
|
|
I don't think that the key parameter is the problem.
The error message "an attempt was made to load a program with an incorrect format" let me suggest that
you try to load an 32 bit dll in an 64 bit application or the the other way round.Greetings
Covean
|
|
|
|
|
I searched the error...and I found the same.
I am using M.Visual Strudio 2008.
It is possible to use this .dll in my application, or i have to load one in 64 bit?
Thanks,
Anca
|
|
|
|
|
Both app and dll must be the same (32 or 64 bit) there is no other way (or maybe I should say I don't know a better way ).
But even if you develop on a 64 bit os you can compile your app as x86 and everything should be fine.Greetings
Covean
|
|
|
|
|
I rebuild the app on 32bit, but now i am receiving "unable to find an entry point named 'ms_md5' in DLL".
I locate the DLL in my \\x86\Debug.
I take dependency walker...to see what functions are in this .dll but i wasn't able to find it.
I found only MD5Init,MD5Update,MD5FInal, but MD5INIT has a parameter type = MD5_CTX.
I can use these functions, but i don;t know how to use MD5_CTX parameter.
Thanks,
Anca
|
|
|
|
|
 Maybe this helps:
[StructLayout(LayoutKind.Sequential)]
public struct MD5_CTX
{
[System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst = 2, ArraySubType = System.Runtime.InteropServices.UnmanagedType.U4)]
public uint[] i;
[System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst = 4, ArraySubType = System.Runtime.InteropServices.UnmanagedType.U4)]
public uint[] buf;
[System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst = 64)]
public byte[] in;
[System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst = 16)]
public byte[] digest;
}
[DllImport("outlfltr.dll")]
public static extern void MD5Init(ref MD5_CTX context);
[DllImport("outlfltr.dll")]
public static extern void MD5Update(ref MD5_CTX context, Byte[] input, Int32 inlen);
[DllImport("outlfltr.dll")]
public static extern void MD5Final(ref MD5_CTX context);
Greetings
Covean
|
|
|
|
|
Hi,
Actually I've done a video player with the last quicktime SDK , and I would like to detect peak in the audio stream.
This peak will serve to synchronise the video stream with a database.
Thanks
|
|
|
|
|
Hi Experts,
I created a program in Visual Studio 2008 Standard. I left the namespace with standard MyProgram. I created some classes like this one
namespace MyProgram
{
public class MyDerivedPanel:Panel
{
}
}
Die werden dann in Form1.Designer.cs behandelt
namespace MyProgram
{
partial class Form1
{
private void InitializeComponent()
{
this.myDerivedPanel1 = new MyProgram.MyDerivedPanel();
}
private MyDerivedPanel myDerivedPanel1;
}
At the mentioned line, Visual Studio claims to have found an error at compile time:
<quote>Error 7 The type "MyDerivedPanel" does not exist in type "MyProgram.MyProgram"
(vaguely translated from german version)
I can delete the namespace including its "." from the erroring line and all works fine. But Visual Studio Designer re-inserts the namespace every time I change something in the Designer.
Having more than one class with this problem, deleting those namespaces gets annoying.
Is that a known issue?
Is there a known solution?Ciao,
luker
|
|
|
|