views:

442

answers:

4

Consider the following code in a class called Worker

    FileSystemWatcher watcher = new FileSystemWatcher();
    public void Run()
    {
        watcher.Path = @"c:\queue";
        watcher.Created += new FileSystemEventHandler(watcher_Created);
        watcher.EnableRaisingEvents = true;
    }

Now here's what I would like to do wih the Worker, but obviouly this doesn't fly.

        Worker worker = new Worker();
        Thread thread = new Thread(worker.Run);
        thread.Start();
        Console.ReadLine(); // something else more interesting would go here.

The reason being that the Run method ends rather than going into some sort of event loop. How do I get an event loop going. (I think I"m looking for something like Application.Run)

A: 

BackgroundWorker, when used with RunAsync(), will run your logic on a seperate thread.

What are you trying to achieve with your worker that involves an event loop? FileSystemWatcher will already be performing an event loop basically for you, so it's unclear what you're trying to achieve here.

Will Eddins
I don't understand what you mean "FileSystemWatcher will already be performing an event loop". Once the Run method ends the path of execution for the thread is finished. The thread is then stopped and so no thread to execute the FileSystemWatcher events.
Ralph Shillington
watcher.EnableRaisingEvents = true; begins the object watching the file system, basically starting the "event loop". When a change happens, the events will be called. Check here for an example: http://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher.enableraisingevents.aspx
Will Eddins
I see what you're attempting to do now. You don't need to do Run() on a separate thread. Once Run() complete, watcher will still exist and be monitoring the file system.
Will Eddins
A: 

Could you just not let the Run() method end until the app is ready to close? Maybe more like: (sorry but I'm tying this by memory not in IDE, so it may not be perfect):

public void Run()
{
    watcher.Path = @"C:\queue";
    watcher.Created += new FileSystemEventHandler(watcher_Created);
    watcher.EnableRaisingEvents = true;

    try
    {
        while(true)
            Thread.Sleep();
    }
    catch(ThreadAbortedException)
    {
        return;
    }
}

and the runner:

Worker worker = new Worker();
Thread thread = new Thread(worker.Run);
thread.Start();
Console.ReadLine(); // something else more interesting would go here.
thread.Abort(); // do when ready to close the app.


On second thought, why are you starting a new thread to do this? Why not just:

watcher.Path = @"C:\queue";
watcher.Created += new FileSystemEventHandler(watcher_Created);
watcher.EnableRaisingEvents = true;
Console.ReadLine(); // something else more interesting would go here.

Or stick your FileSystemWatcher in a variable somewhere that won't go out of scope (on the main form if a WinForms app, or whatever class has the Main() method if a console app).

Or is there other stuff going on here that isn't shown?

rally25rs
A "while(true) Sleep" loop doesn't seem like a good idea. How do you abort the program? Furthermore, if you're just doing it to wait on some thread finishing, you can just use the Thread.join method.
IRBMe
the thread.Abort() call from the original thread would cause a ThreadAbortedException in the 2nd thread and it should exit at that point. Agreed though that its far from flawless. The point was that in the original post, leaving the Run() method caused watcher to go out of scope and be disposed, so no more events. Hence the "stay in Run() indefinitely" solution. Though really, i don't think it should be done in a 2nd thread anyway...
rally25rs
+1  A: 

Pulled from MSDN

Worker worker = new Worker();
Thread thread = new ThreadStart(worker.Run);
thread.Start();
// Not sure if you need this while
while (!oThread.IsAlive);
oThread.Join();
Console.ReadLine();
Rorschach
No, "while" is best replaced by "if" since Thread.Join() is a blocking call.
Maxime Labelle
@Maxime: The "while" is being used to wait until the thread is alive. I don't think it's actually needed in this case, but it isn't being used for what you think. The "if" you suggested also isn't needed.
Sean Nyman
+1  A: 

Not tested, but your "event" loop, if you're wanting it to run on the thread, would look something like this:

private bool running = true;
private AutoResetEvent waiter = new AutoResetEvent(false);

public void Run()
{
 FileSystemWatcher watcher = new FileSystemWatcher("C:\\");
 FileSystemEventArgs changes = null;

 watcher.Changed +=
  (object sender, FileSystemEventArgs e) => {
   changes = e;
   waiter.Set();
  };

 watcher.EnableRaisingEvents = true;

 while (running)
 {
  waiter.WaitOne();
  if (!running) break;

  Console.WriteLine("Path: {0}, Type: {1}",
    changes.FullPath, changes.ChangeType);
 }

 Console.WriteLine("Thread complete");
}

public void Stop()
{
 running = false;
 waiter.Set();
}

You would place this code in a class and run it on a separate thread (if you wish). If you want to have your main thread wait on the thread you create finishing (although why bother creating a thread in that case?) then you can use the Thread.Join method.

IRBMe