Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public FileSystemEventArgs(System.IO.WatcherChangeTypes changeType, string direc
public string Name { get { throw null; } }
}
public delegate void FileSystemEventHandler(object sender, System.IO.FileSystemEventArgs e);
public partial class FileSystemWatcher : System.ComponentModel.Component
public partial class FileSystemWatcher : System.ComponentModel.Component, System.ComponentModel.ISupportInitialize
{
public FileSystemWatcher() { }
public FileSystemWatcher(string path) { }
Expand All @@ -45,6 +45,11 @@ protected void OnError(System.IO.ErrorEventArgs e) { }
protected void OnRenamed(System.IO.RenamedEventArgs e) { }
public System.IO.WaitForChangedResult WaitForChanged(System.IO.WatcherChangeTypes changeType) { throw null; }
public System.IO.WaitForChangedResult WaitForChanged(System.IO.WatcherChangeTypes changeType, int timeout) { throw null; }
public override System.ComponentModel.ISite Site { get { throw null; } set { } }
public System.ComponentModel.ISynchronizeInvoke SynchronizingObject { get { throw null; } set { } }
public void BeginInit() { }
protected override void Dispose(bool disposing) { }
public void EndInit() { }
}
[Serializable]
public partial class InternalBufferOverflowException : System.SystemException
Expand Down
3 changes: 2 additions & 1 deletion src/System.IO.FileSystem.Watcher/ref/project.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
{
"dependencies": {
"System.Runtime": "4.4.0-beta-24715-03",
"System.ComponentModel.Primitives": "4.4.0-beta-24715-03"
"System.ComponentModel.Primitives": "4.4.0-beta-24715-03",
"System.ComponentModel.TypeConverter": "4.4.0-beta-24715-03"
},
"frameworks": {
"netstandard1.7": {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@ public partial class FileSystemWatcher
/// <summary>Starts a new watch operation if one is not currently running.</summary>
private void StartRaisingEvents()
{
// If we're called when "Initializing" is true, set enabled to true
if (IsSuspended())
{
_enabled = true;
return;
}

// If we already have a cancellation object, we're already running.
if (_cancellation != null)
{
Expand Down Expand Up @@ -88,6 +95,9 @@ private void StopRaisingEvents()
{
_enabled = false;

if (IsSuspended())
return;

// If there's an active cancellation token, cancel and release it.
// The cancellation token and the processing task respond to cancellation
// to handle all other cleanup.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,13 @@ private void FinalizeDispose()

private void StartRaisingEvents()
{
// If we're called when "Initializing" is true, set enabled to true
if (IsSuspended())
{
_enabled = true;
return;
}

// Don't start another instance if one is already runnings
if (_cancellation != null)
{
Expand All @@ -53,6 +60,9 @@ private void StopRaisingEvents()
{
_enabled = false;

if (IsSuspended())
return;

CancellationTokenSource token = _cancellation;
if (token != null)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@ public partial class FileSystemWatcher
/// <summary>Start monitoring the current directory.</summary>
private void StartRaisingEvents()
{
// If we're called when "Initializing" is true, set enabled to true
if (IsSuspended())
{
_enabled = true;
return;
}

// If we're already running, don't do anything.
if (!IsHandleInvalid(_directoryHandle))
return;
Expand Down Expand Up @@ -67,6 +74,9 @@ private void StopRaisingEvents()
{
_enabled = false;

if (IsSuspended())
return;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When will the subsequent logic be invoked in this case?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It won't be. When under initialization, the only action StopRaisingEvents does is to set _enabled to false since actual event watching is paused/stopped/hasn't begun.

This state is reached by first called BeginInit() which will call StopRaisingEvents before setting _enabled, so before we get into an IsSuspended state we will have done the subsequent cleanup necessary.

So the assertion is that when IsSuspended is true, we already did the other stuff in StopRaisingEvents and don't need to do it again.

This is ripped from the desktop code.


// If we're not running, do nothing.
if (IsHandleInvalid(_directoryHandle))
return;
Expand Down
127 changes: 115 additions & 12 deletions src/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.

using System.ComponentModel;
using System.ComponentModel.Design;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Threading;
Expand All @@ -15,7 +16,7 @@ namespace System.IO
/// raises events when a directory or file within a directory changes.
/// </devdoc>

public partial class FileSystemWatcher : Component
public partial class FileSystemWatcher : Component, ISupportInitialize
{
/// <devdoc>
/// Private instance variables
Expand All @@ -36,11 +37,15 @@ public partial class FileSystemWatcher : Component
// Flag to note whether we are attached to the thread pool and responding to changes
private bool _enabled = false;

// Are we in init?
private bool _initializing = false;

// Buffer size
private int _internalBufferSize = 8192;

// Used for synchronization
private bool _disposed;
private ISynchronizeInvoke _synchronizingObject;

// Event handlers
private FileSystemEventHandler _onChangedHandler = null;
Expand Down Expand Up @@ -146,14 +151,21 @@ public bool EnableRaisingEvents
{
return;
}

if (value)
if (IsSuspended())
{
StartRaisingEventsIfNotDisposed(); // will set _enabled to true once successfully started
_enabled = value; // Alert the Component to start watching for events when EndInit is called.
}
else
{
StopRaisingEvents(); // will set _enabled to false
{
if (value)
{
StartRaisingEventsIfNotDisposed(); // will set _enabled to true once successfully started
}
else
{
StopRaisingEvents(); // will set _enabled to false
}
}
}
}
Expand Down Expand Up @@ -371,6 +383,7 @@ protected override void Dispose(bool disposing)
finally
{
_disposed = true;
base.Dispose(disposing);
}
}

Expand Down Expand Up @@ -446,7 +459,7 @@ private void NotifyFileSystemEventArgs(WatcherChangeTypes changeType, string nam
[SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#", Justification = "Changing from protected to private would be a breaking change")]
protected void OnChanged(FileSystemEventArgs e)
{
_onChangedHandler?.Invoke(this, e);
InvokeOn(e, _onChangedHandler);
}

/// <devdoc>
Expand All @@ -455,7 +468,7 @@ protected void OnChanged(FileSystemEventArgs e)
[SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#", Justification = "Changing from protected to private would be a breaking change")]
protected void OnCreated(FileSystemEventArgs e)
{
_onCreatedHandler?.Invoke(this, e);
InvokeOn(e, _onCreatedHandler);
}

/// <devdoc>
Expand All @@ -464,7 +477,19 @@ protected void OnCreated(FileSystemEventArgs e)
[SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#", Justification = "Changing from protected to private would be a breaking change")]
protected void OnDeleted(FileSystemEventArgs e)
{
_onDeletedHandler?.Invoke(this, e);
InvokeOn(e, _onDeletedHandler);
}

private void InvokeOn(FileSystemEventArgs e, FileSystemEventHandler handler)
{
if (handler != null)
{
ISynchronizeInvoke syncObj = SynchronizingObject;
if (syncObj != null && syncObj.InvokeRequired)
syncObj.BeginInvoke(handler, new object[] { this, e });
else
handler(this, e);
}
}

/// <devdoc>
Expand All @@ -473,7 +498,15 @@ protected void OnDeleted(FileSystemEventArgs e)
[SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#", Justification = "Changing from protected to private would be a breaking change")]
protected void OnError(ErrorEventArgs e)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

InvokeOn(e, _onErrorHandler);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't use the InvokeOn helper for Renamed and Error because of the different handler/args types that do not share a common parent.

{
_onErrorHandler?.Invoke(this, e);
ErrorEventHandler handler = _onErrorHandler;
if (handler != null)
{
ISynchronizeInvoke syncObj = SynchronizingObject;
if (syncObj != null && syncObj.InvokeRequired)
syncObj.BeginInvoke(handler, new object[] { this, e });
else
handler(this, e);
}
}

/// <devdoc>
Expand All @@ -482,7 +515,15 @@ protected void OnError(ErrorEventArgs e)
[SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#", Justification = "Changing from protected to private would be a breaking change")]
protected void OnRenamed(RenamedEventArgs e)
{
_onRenamedHandler?.Invoke(this, e);
RenamedEventHandler handler = _onRenamedHandler;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

InvokeOn(e, _onRenamedHandler);

if (handler != null)
{
ISynchronizeInvoke syncObj = SynchronizingObject;
if (syncObj != null && syncObj.InvokeRequired)
syncObj.BeginInvoke(handler, new object[] { this, e });
else
handler(this, e);
}
}

public WaitForChangedResult WaitForChanged(WatcherChangeTypes changeType) =>
Expand Down Expand Up @@ -566,7 +607,7 @@ public WaitForChangedResult WaitForChanged(WatcherChangeTypes changeType, int ti
/// <internalonly/>
private void Restart()
{
if (_enabled)
if ((!IsSuspended()) && _enabled)
{
StopRaisingEvents();
StartRaisingEventsIfNotDisposed();
Expand All @@ -580,5 +621,67 @@ private void StartRaisingEventsIfNotDisposed()
throw new ObjectDisposedException(GetType().Name);
StartRaisingEvents();
}

public override ISite Site
{
get
{
return base.Site;
}
set
{
base.Site = value;

// set EnableRaisingEvents to true at design time so the user
// doesn't have to manually.
if (Site != null && Site.DesignMode)
EnableRaisingEvents = true;
}
}

public ISynchronizeInvoke SynchronizingObject
{
get
{
if (_synchronizingObject == null && DesignMode)
{
IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost));
if (host != null)
{
object baseComponent = host.RootComponent;
if (baseComponent != null && baseComponent is ISynchronizeInvoke)
_synchronizingObject = (ISynchronizeInvoke)baseComponent;
}
}

return _synchronizingObject;
}

set
{
_synchronizingObject = value;
}
}

public void BeginInit()
{
bool oldEnabled = _enabled;
StopRaisingEvents();
_enabled = oldEnabled;
_initializing = true;
}

public void EndInit()
{
_initializing = false;
// Start listening to events if _enabled was set to true at some point.
if (_directory.Length != 0 && _enabled)
StartRaisingEvents();
}

private bool IsSuspended()
{
return _initializing || DesignMode;
}
}
}
1 change: 1 addition & 0 deletions src/System.IO.FileSystem.Watcher/src/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"Microsoft.Win32.Primitives": "4.4.0-beta-24715-03",
"System.Collections": "4.4.0-beta-24715-03",
"System.ComponentModel.Primitives": "4.4.0-beta-24715-03",
"System.ComponentModel.TypeConverter": "4.4.0-beta-24715-03",
"System.Diagnostics.Debug": "4.4.0-beta-24715-03",
"System.Diagnostics.Tools": "4.4.0-beta-24715-03",
"System.IO": "4.4.0-beta-24715-03",
Expand Down
Loading