views:

98

answers:

6

Hello I've runned in to a problem again that I can't solve on my own.

I have a FileSystemWatcher named filOvervakare and uses this code to trigger a method.

filOvervakare.NotifyFilter = NotifyFilters.Size;
filOvervakare.NotifyFilter = NotifyFilters.LastWrite;

filOvervakare.Changed += new FileSystemEventHandler(filOvervakare_Changed);

This is the method:

void filOvervakare_Changed(object sender, FileSystemEventArgs e)
{
    if (MessageBox.Show("Vill du ladda upp filen " + e.Name + "?", "En fil har ändrats", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
    {
        //code code code           
    }
}

Everytime a file is changed it is supposed to show the messagebox once. The problem is that instead of getting one messagebox it pops up like 5-6 of them and I have no idea how to fix this and I hope some of you might have a good solution. :)

Thanks!

// Morgan

+1  A: 

You could use a boolean to tell you whether you have a message box open.

private bool messageBoxIsOpen;

void filOvervakare_Changed(object sender, FileSystemEventArgs e)
{
    if (this.messageBoxIsOpen)
    {
        return;
    }

    this.messageBoxIsOpen = true;
    if (MessageBox.Show(
        "Vill du ladda upp filen " + e.Name + "?", 
        "En fil har ändrats", 
        MessageBoxButtons.YesNo, 
        MessageBoxIcon.Question) == DialogResult.Yes)
    {
       //code code code           
    }

    this.messageBoxIsOpen = false;
}
Zach Johnson
+2  A: 

This is by design, the event handler is called on a different thread for each notification. A quick fix is to set the FileSystemWatcher.SynchronizingObject property:

    public Form1() {
        InitializeComponent();
        fileSystemWatcher1.SynchronizingObject = this;
    }

But that's not a really good idea, the FSW is liable to miss notifications because it is blocked, waiting for you to click the OK button. Displaying a message box in the notification event is just not a good idea, you want to process the notifications as quickly as possible.

Hans Passant
@nobugz: **the event handler is called on a different thread for each notification** needs citation please.
Sameh Serag
@sameh: Isn't 6 message boxes enough proof?
Hans Passant
A: 

The easiest way to fix this is to declare a private bool, like so:

private bool m_IsBoxShown;

In your constructor, set the value to false. Change your code above to read like this: void filOvervakare_Changed(object sender, FileSystemEventArgs e)
{
if (m_IsBoxShown == false) { m_IsBoxShown=true; if (MessageBox.Show("Vill du ladda upp filen " + e.Name + "?", "En fil har ändrats", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
{
m_IsBoxShown=false; //code code code
} else { m_IsBoxShown=false; } } }

icemanind
+1  A: 

There are a few events, something like LastAccess, LastWrite etc that the file system watcher fires events on. You could check the event args for why the event was fired before displaying the message box or set the NotifyFilter property.

tarn
A: 

What I would recommend is having a short delay, say 10-100ms before showing the MessageBox. That way when a file changes a few times very quickly you only get one MessageBox.

In other words, when a notification comes in, start the timer. If the timer is already started, ignore the notification. When the timer triggers, stop the timer and show the MessageBox.

Gabe
+1  A: 

You can save the last changed file name in a dummy variable, and when the changed event is raised, don't show the messagebox unless the file name is different to the saved variable.

string lastChangedFileName = "";
void filOvervakare_Changed(object sender, FileSystemEventArgs e)
    {

if(lastChangedFileName != e.Name)
{
        if (MessageBox.Show("Vill du ladda upp filen " + e.Name + "?", "En fil har ändrats", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
        {
           //code code code           
        }
}
lastChangedFileName = e.Name;

    }
Sameh Serag
Thanks this was the easíest solution! And thanks everyone else for a quck response with different ways to slove my problem! //Morgan
Morgan.Spagetti
Shouldn't `lastChangedFileName = e.Name;` be inside the `if` statement before the message box is shown? Otherwise `lastChangedFileName` will only be set after the message box is closed, and it will be set *every* time the event is raised.
Zach Johnson
+1: Thanks Zach, you are right ;-)
Sameh Serag