I use a combination of IVsFileChangeEvents
and IVsFileChangeEx
to monitor, whether file edited in my custom editor extension was modified outside the IDE. However, for some unknown reason, I get the notification twice - thus resulting in asking user for reload twice.
The implementation of FilesChanged looks like the following:
public int FilesChanged(uint cChanges, string[] rgpszFile, uint[] rggrfChange) {
foreach (var file in rgpszFile)
{
if (file.ToLowerInvariant() == documentPath.ToLowerInvariant()) {
System.Diagnostics.Debug.WriteLine("File changed - asking for reload");
if (MessageBox.Show("The file {0} was changed outside the editor. Do you want to reload it?".FillWith(file),
"MyEditor",
MessageBoxButton.YesNo,
MessageBoxImage.Question) == MessageBoxResult.Yes) {
fileChangeEx.IgnoreFile(fileCookie, null, 1);
// Unloading document
DoCloseDocument();
// Loading document
DoLoadDocument(file);
fileChangeEx.SyncFile(documentPath);
fileChangeEx.IgnoreFile(fileCookie, null, 0);
}
}
}
return VSConstants.S_OK;
}
I test this code by saving the same file in Notepad++.
This is a log from SysInternals' ProcMon:
09:05:21,2272369 notepad++.exe 256 QueryOpen D:\VS Projects\Temporary\WindowsFormsApplication1\WindowsFormsApplication1\NewFolder1\settings.definition SUCCESS CreationTime: 2014-05-21 13:08:34, LastAccessTime: 2014-05-21 13:08:34, LastWriteTime: 2014-05-23 08:50:27, ChangeTime: 2014-05-23 08:50:27, AllocationSize: 4 096, EndOfFile: 1 740, FileAttributes: A
09:05:21,2273658 notepad++.exe 256 QueryOpen D:\VS Projects\Temporary\WindowsFormsApplication1\WindowsFormsApplication1\NewFolder1\settings.definition SUCCESS CreationTime: 2014-05-21 13:08:34, LastAccessTime: 2014-05-21 13:08:34, LastWriteTime: 2014-05-23 08:50:27, ChangeTime: 2014-05-23 08:50:27, AllocationSize: 4 096, EndOfFile: 1 740, FileAttributes: A
09:05:21,2275512 notepad++.exe 256 QueryDirectory D:\VS Projects\Temporary\WindowsFormsApplication1\WindowsFormsApplication1\NewFolder1\settings.definition SUCCESS Filter: settings.definition, 1: settings.definition
09:05:28,7692878 notepad++.exe 256 QueryOpen D:\VS Projects\Temporary\WindowsFormsApplication1\WindowsFormsApplication1\NewFolder1\settings.definition SUCCESS CreationTime: 2014-05-21 13:08:34, LastAccessTime: 2014-05-21 13:08:34, LastWriteTime: 2014-05-23 08:50:27, ChangeTime: 2014-05-23 08:50:27, AllocationSize: 4 096, EndOfFile: 1 740, FileAttributes: A
09:05:28,7694244 notepad++.exe 256 QueryOpen D:\VS Projects\Temporary\WindowsFormsApplication1\WindowsFormsApplication1\NewFolder1\settings.definition SUCCESS CreationTime: 2014-05-21 13:08:34, LastAccessTime: 2014-05-21 13:08:34, LastWriteTime: 2014-05-23 08:50:27, ChangeTime: 2014-05-23 08:50:27, AllocationSize: 4 096, EndOfFile: 1 740, FileAttributes: A
09:05:28,7696066 notepad++.exe 256 QueryDirectory D:\VS Projects\Temporary\WindowsFormsApplication1\WindowsFormsApplication1\NewFolder1\settings.definition SUCCESS Filter: settings.definition, 1: settings.definition
09:05:44,0463636 notepad++.exe 256 QueryOpen D:\VS Projects\Temporary\WindowsFormsApplication1\WindowsFormsApplication1\NewFolder1\settings.definition SUCCESS CreationTime: 2014-05-21 13:08:34, LastAccessTime: 2014-05-21 13:08:34, LastWriteTime: 2014-05-23 08:50:27, ChangeTime: 2014-05-23 08:50:27, AllocationSize: 4 096, EndOfFile: 1 740, FileAttributes: A
09:05:46,4087520 notepad++.exe 256 QueryOpen D:\VS Projects\Temporary\WindowsFormsApplication1\WindowsFormsApplication1\NewFolder1\settings.definition SUCCESS CreationTime: 2014-05-21 13:08:34, LastAccessTime: 2014-05-21 13:08:34, LastWriteTime: 2014-05-23 08:50:27, ChangeTime: 2014-05-23 08:50:27, AllocationSize: 4 096, EndOfFile: 1 740, FileAttributes: A
09:05:46,4088700 notepad++.exe 256 QueryOpen D:\VS Projects\Temporary\WindowsFormsApplication1\WindowsFormsApplication1\NewFolder1\settings.definition SUCCESS CreationTime: 2014-05-21 13:08:34, LastAccessTime: 2014-05-21 13:08:34, LastWriteTime: 2014-05-23 08:50:27, ChangeTime: 2014-05-23 08:50:27, AllocationSize: 4 096, EndOfFile: 1 740, FileAttributes: A
09:05:46,4089646 notepad++.exe 256 QueryOpen D:\VS Projects\Temporary\WindowsFormsApplication1\WindowsFormsApplication1\NewFolder1\settings.definition SUCCESS CreationTime: 2014-05-21 13:08:34, LastAccessTime: 2014-05-21 13:08:34, LastWriteTime: 2014-05-23 08:50:27, ChangeTime: 2014-05-23 08:50:27, AllocationSize: 4 096, EndOfFile: 1 740, FileAttributes: A
09:05:46,4090631 notepad++.exe 256 CreateFile D:\VS Projects\Temporary\WindowsFormsApplication1\WindowsFormsApplication1\NewFolder1\settings.definition SUCCESS Desired Access: Generic Write, Read Attributes, Dis, Options: Synchronous IO Non-Alert, Non-Directory File, Attributes: N, ShareMode: Read, Write, AllocationSize: 0, OpenResult: Overwritten
09:05:46,4100654 notepad++.exe 256 WriteFile D:\VS Projects\Temporary\WindowsFormsApplication1\WindowsFormsApplication1\NewFolder1\settings.definition SUCCESS Offset: 0, Length: 1 742, Priority: Normal
09:05:46,4101850 notepad++.exe 256 CloseFile D:\VS Projects\Temporary\WindowsFormsApplication1\WindowsFormsApplication1\NewFolder1\settings.definition SUCCESS
09:05:46,4102751 devenv.exe 6884 QueryOpen D:\VS Projects\Temporary\WindowsFormsApplication1\WindowsFormsApplication1\NewFolder1\settings.definition SUCCESS CreationTime: 2014-05-21 13:08:34, LastAccessTime: 2014-05-21 13:08:34, LastWriteTime: 2014-05-23 09:05:46, ChangeTime: 2014-05-23 09:05:46, AllocationSize: 4 096, EndOfFile: 1 742, FileAttributes: A
09:05:46,4103088 MsMpEng.exe 956 CreateFileMapping D:\VS Projects\Temporary\WindowsFormsApplication1\WindowsFormsApplication1\NewFolder1\settings.definition FILE LOCKED WITH WRITERS SyncType: SyncTypeCreateSection, PageProtection:
09:05:46,4103322 MsMpEng.exe 956 QueryStandardInformationFile D:\VS Projects\Temporary\WindowsFormsApplication1\WindowsFormsApplication1\NewFolder1\settings.definition SUCCESS AllocationSize: 4 096, EndOfFile: 1 742, NumberOfLinks: 1, DeletePending: False, Directory: False
09:05:46,4144664 notepad++.exe 256 QueryDirectory D:\VS Projects\Temporary\WindowsFormsApplication1\WindowsFormsApplication1\NewFolder1\settings.definition SUCCESS Filter: settings.definition, 1: settings.definition
09:05:46,4160238 notepad++.exe 256 QueryOpen D:\VS Projects\Temporary\WindowsFormsApplication1\WindowsFormsApplication1\NewFolder1\settings.definition SUCCESS CreationTime: 2014-05-21 13:08:34, LastAccessTime: 2014-05-21 13:08:34, LastWriteTime: 2014-05-23 09:05:46, ChangeTime: 2014-05-23 09:05:46, AllocationSize: 4 096, EndOfFile: 1 742, FileAttributes: A
09:05:46,4172362 notepad++.exe 256 QueryOpen D:\VS Projects\Temporary\WindowsFormsApplication1\WindowsFormsApplication1\NewFolder1\settings.definition SUCCESS CreationTime: 2014-05-21 13:08:34, LastAccessTime: 2014-05-21 13:08:34, LastWriteTime: 2014-05-23 09:05:46, ChangeTime: 2014-05-23 09:05:46, AllocationSize: 4 096, EndOfFile: 1 742, FileAttributes: A
09:05:46,4173472 notepad++.exe 256 QueryOpen D:\VS Projects\Temporary\WindowsFormsApplication1\WindowsFormsApplication1\NewFolder1\settings.definition SUCCESS CreationTime: 2014-05-21 13:08:34, LastAccessTime: 2014-05-21 13:08:34, LastWriteTime: 2014-05-23 09:05:46, ChangeTime: 2014-05-23 09:05:46, AllocationSize: 4 096, EndOfFile: 1 742, FileAttributes: A
09:05:46,4175063 notepad++.exe 256 QueryDirectory D:\VS Projects\Temporary\WindowsFormsApplication1\WindowsFormsApplication1\NewFolder1\settings.definition SUCCESS Filter: settings.definition, 1: settings.definition
09:05:46,4178437 notepad++.exe 256 QueryOpen D:\VS Projects\Temporary\WindowsFormsApplication1\WindowsFormsApplication1\NewFolder1\settings.definition SUCCESS CreationTime: 2014-05-21 13:08:34, LastAccessTime: 2014-05-21 13:08:34, LastWriteTime: 2014-05-23 09:05:46, ChangeTime: 2014-05-23 09:05:46, AllocationSize: 4 096, EndOfFile: 1 742, FileAttributes: A
09:05:46,4185672 notepad++.exe 256 QueryOpen D:\VS Projects\Temporary\WindowsFormsApplication1\WindowsFormsApplication1\NewFolder1\settings.definition SUCCESS CreationTime: 2014-05-21 13:08:34, LastAccessTime: 2014-05-21 13:08:34, LastWriteTime: 2014-05-23 09:05:46, ChangeTime: 2014-05-23 09:05:46, AllocationSize: 4 096, EndOfFile: 1 742, FileAttributes: A
09:05:46,4186404 devenv.exe 6884 QueryOpen D:\VS Projects\Temporary\WindowsFormsApplication1\WindowsFormsApplication1\NewFolder1\settings.definition SUCCESS CreationTime: 2014-05-21 13:08:34, LastAccessTime: 2014-05-21 13:08:34, LastWriteTime: 2014-05-23 09:05:46, ChangeTime: 2014-05-23 09:05:46, AllocationSize: 4 096, EndOfFile: 1 742, FileAttributes: A
09:06:06,8788282 notepad++.exe 256 QueryOpen D:\VS Projects\Temporary\WindowsFormsApplication1\WindowsFormsApplication1\NewFolder1\settings.definition SUCCESS CreationTime: 2014-05-21 13:08:34, LastAccessTime: 2014-05-21 13:08:34, LastWriteTime: 2014-05-23 09:05:46, ChangeTime: 2014-05-23 09:05:46, AllocationSize: 4 096, EndOfFile: 1 742, FileAttributes: A
09:06:06,8789555 notepad++.exe 256 QueryOpen D:\VS Projects\Temporary\WindowsFormsApplication1\WindowsFormsApplication1\NewFolder1\settings.definition SUCCESS CreationTime: 2014-05-21 13:08:34, LastAccessTime: 2014-05-21 13:08:34, LastWriteTime: 2014-05-23 09:05:46, ChangeTime: 2014-05-23 09:05:46, AllocationSize: 4 096, EndOfFile: 1 742, FileAttributes: A
09:06:06,8791373 notepad++.exe 256 QueryDirectory D:\VS Projects\Temporary\WindowsFormsApplication1\WindowsFormsApplication1\NewFolder1\settings.definition SUCCESS Filter: settings.definition, 1: settings.definition
09:06:50,6465883 devenv.exe 6884 CreateFile D:\VS Projects\Temporary\WindowsFormsApplication1\WindowsFormsApplication1\NewFolder1\settings.definition SUCCESS Desired Access: Generic Read, Dis, Options: Synchronous IO Non-Alert, Non-Directory File, Open No Recall, Attributes: n/a, ShareMode: Read, AllocationSize: n/a, OpenResult: Opened
09:06:50,6466482 devenv.exe 6884 QueryStandardInformationFile D:\VS Projects\Temporary\WindowsFormsApplication1\WindowsFormsApplication1\NewFolder1\settings.definition SUCCESS AllocationSize: 4 096, EndOfFile: 1 742, NumberOfLinks: 1, DeletePending: False, Directory: False
09:06:50,6466665 devenv.exe 6884 ReadFile D:\VS Projects\Temporary\WindowsFormsApplication1\WindowsFormsApplication1\NewFolder1\settings.definition SUCCESS Offset: 0, Length: 1 742, Priority: Normal
09:06:50,6467374 devenv.exe 6884 ReadFile D:\VS Projects\Temporary\WindowsFormsApplication1\WindowsFormsApplication1\NewFolder1\settings.definition END OF FILE Offset: 1 742, Length: 4 096
09:06:50,6469314 devenv.exe 6884 CloseFile D:\VS Projects\Temporary\WindowsFormsApplication1\WindowsFormsApplication1\NewFolder1\settings.definition SUCCESS
09:06:50,6477175 devenv.exe 6884 QueryOpen D:\VS Projects\Temporary\WindowsFormsApplication1\WindowsFormsApplication1\NewFolder1\settings.definition SUCCESS CreationTime: 2014-05-21 13:08:34, LastAccessTime: 2014-05-21 13:08:34, LastWriteTime: 2014-05-23 09:05:46, ChangeTime: 2014-05-23 09:05:46, AllocationSize: 4 096, EndOfFile: 1 742, FileAttributes: A
09:06:50,6963339 devenv.exe 6884 QueryOpen D:\VS Projects\Temporary\WindowsFormsApplication1\WindowsFormsApplication1\NewFolder1\settings.definition SUCCESS CreationTime: 2014-05-21 13:08:34, LastAccessTime: 2014-05-21 13:08:34, LastWriteTime: 2014-05-23 09:05:46, ChangeTime: 2014-05-23 09:05:46, AllocationSize: 4 096, EndOfFile: 1 742, FileAttributes: A
09:07:02,3340501 devenv.exe 6884 CreateFile D:\VS Projects\Temporary\WindowsFormsApplication1\WindowsFormsApplication1\NewFolder1\settings.definition SUCCESS Desired Access: Generic Read, Dis, Options: Synchronous IO Non-Alert, Non-Directory File, Open No Recall, Attributes: n/a, ShareMode: Read, AllocationSize: n/a, OpenResult: Opened
09:07:02,3341050 devenv.exe 6884 QueryStandardInformationFile D:\VS Projects\Temporary\WindowsFormsApplication1\WindowsFormsApplication1\NewFolder1\settings.definition SUCCESS AllocationSize: 4 096, EndOfFile: 1 742, NumberOfLinks: 1, DeletePending: False, Directory: False
09:07:02,3341200 devenv.exe 6884 ReadFile D:\VS Projects\Temporary\WindowsFormsApplication1\WindowsFormsApplication1\NewFolder1\settings.definition SUCCESS Offset: 0, Length: 1 742, Priority: Normal
09:07:02,3341887 devenv.exe 6884 ReadFile D:\VS Projects\Temporary\WindowsFormsApplication1\WindowsFormsApplication1\NewFolder1\settings.definition END OF FILE Offset: 1 742, Length: 4 096
09:07:02,3343792 devenv.exe 6884 CloseFile D:\VS Projects\Temporary\WindowsFormsApplication1\WindowsFormsApplication1\NewFolder1\settings.definition SUCCESS
09:07:02,3351733 devenv.exe 6884 QueryOpen D:\VS Projects\Temporary\WindowsFormsApplication1\WindowsFormsApplication1\NewFolder1\settings.definition SUCCESS CreationTime: 2014-05-21 13:08:34, LastAccessTime: 2014-05-21 13:08:34, LastWriteTime: 2014-05-23 09:05:46, ChangeTime: 2014-05-23 09:05:46, AllocationSize: 4 096, EndOfFile: 1 742, FileAttributes: A
09:07:02,3626280 devenv.exe 6884 QueryOpen D:\VS Projects\Temporary\WindowsFormsApplication1\WindowsFormsApplication1\NewFolder1\settings.definition SUCCESS CreationTime: 2014-05-21 13:08:34, LastAccessTime: 2014-05-21 13:08:34, LastWriteTime: 2014-05-23 09:05:46, ChangeTime: 2014-05-23 09:05:46, AllocationSize: 4 096, EndOfFile: 1 742, FileAttributes: A
It seems like the MessageBox.Show call is the main reason for the second notification.
The call stack looks like the following:
MyAssembly.dll!MyClass.FilesChanged(uint cChanges = 1, string[] rgpszFile = {string[1]}, uint[] rggrfChange = {uint[1]}) Line 284 C#
Microsoft.VisualStudio.Shell.UI.Internal.dll!Microsoft.VisualStudio.Services.FileChangeSubscription.Notify.AnonymousMethod__0() Unknown
Microsoft.VisualStudio.Shell.12.0.dll!Microsoft.VisualStudio.ErrorHandler.CallWithCOMConvention(System.Func<int> method, bool reportError = false, bool setShellErrorInfo = true) Unknown
Microsoft.VisualStudio.Shell.UI.Internal.dll!Microsoft.VisualStudio.Services.FileChangeSubscription.Notify(Microsoft.VisualStudio.Shell.Interop._VSFILECHANGEFLAGS changes) Unknown
Microsoft.VisualStudio.Shell.UI.Internal.dll!Microsoft.VisualStudio.Services.FileChangeSubscription.Notify(System.IO.WatcherChangeTypes changeTypes, Microsoft.VisualStudio.Services.FileProperties props) Unknown
Microsoft.VisualStudio.Shell.UI.Internal.dll!Microsoft.VisualStudio.Services.FileWatcher.Notify(Microsoft.VisualStudio.Services.ChangeStreamDigest digest) Unknown
Microsoft.VisualStudio.Shell.UI.Internal.dll!Microsoft.VisualStudio.Services.DirectoryWatcher.ProcessFileChanges(System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<string,Microsoft.VisualStudio.Services.ChangeStreamDigest>> digests, int depth) Unknown
Microsoft.VisualStudio.Shell.UI.Internal.dll!Microsoft.VisualStudio.Services.DirectoryWatcher.ProcessChanges(System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<string,Microsoft.VisualStudio.Services.ChangeStreamDigest>> digests = Count = 1, int depth = 3) Unknown
Microsoft.VisualStudio.Shell.UI.Internal.dll!Microsoft.VisualStudio.Services.DirectoryWatcher.ProcessChanges(System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<string,Microsoft.VisualStudio.Services.ChangeStreamDigest>> digests = Count = 1, int depth = 2) Unknown
Microsoft.VisualStudio.Shell.UI.Internal.dll!Microsoft.VisualStudio.Services.DirectoryWatcher.ProcessChanges(System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<string,Microsoft.VisualStudio.Services.ChangeStreamDigest>> digests = {Microsoft.Internal.VisualStudio.PlatformUI.HybridDictionary<string,Microsoft.VisualStudio.Services.ChangeStreamDigest>}, int depth = 1) Unknown
Microsoft.VisualStudio.Shell.UI.Internal.dll!Microsoft.VisualStudio.Services.DirectoryWatcher.OnChangedAsync() Unknown
WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate callback, object args, int numArgs) Unknown
WindowsBase.dll!MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(object source = {System.Windows.Threading.Dispatcher}, System.Delegate method, object args, int numArgs, System.Delegate catchHandler = null) Unknown
WindowsBase.dll!System.Windows.Threading.DispatcherOperation.InvokeImpl() Unknown
WindowsBase.dll!System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(object state) Unknown
mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) Unknown
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) Unknown
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) Unknown
WindowsBase.dll!System.Windows.Threading.DispatcherOperation.Invoke() Unknown
WindowsBase.dll!System.Windows.Threading.Dispatcher.ProcessQueue() Unknown
WindowsBase.dll!System.Windows.Threading.Dispatcher.WndProcHook(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled) Unknown
WindowsBase.dll!MS.Win32.HwndWrapper.WndProc(System.IntPtr hwnd = 264738, int msg = 49778, System.IntPtr wParam = 0, System.IntPtr lParam = 0, ref bool handled = false) Unknown
WindowsBase.dll!MS.Win32.HwndSubclass.DispatcherCallbackOperation(object o) Unknown
WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate callback, object args, int numArgs) Unknown
WindowsBase.dll!MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(object source = {System.Windows.Threading.Dispatcher}, System.Delegate method, object args, int numArgs, System.Delegate catchHandler = null) Unknown
WindowsBase.dll!System.Windows.Threading.Dispatcher.LegacyInvokeImpl(System.Windows.Threading.DispatcherPriority priority, System.TimeSpan timeout, System.Delegate method, object args, int numArgs) Unknown
WindowsBase.dll!MS.Win32.HwndSubclass.SubclassWndProc(System.IntPtr hwnd = 264738, int msg = 49778, System.IntPtr wParam = 0, System.IntPtr lParam = 0) Unknown
[Native to Managed Transition]
[Managed to Native Transition]
PresentationFramework.dll!System.Windows.MessageBox.ShowCore(System.IntPtr owner, string messageBoxText, string caption, System.Windows.MessageBoxButton button, System.Windows.MessageBoxImage icon, System.Windows.MessageBoxResult defaultResult, System.Windows.MessageBoxOptions options) Unknown
PresentationFramework.dll!System.Windows.MessageBox.Show(string messageBoxText, string caption, System.Windows.MessageBoxButton button, System.Windows.MessageBoxImage icon) Unknown
MyAssembly.dll!MyClass.FilesChanged(uint cChanges = 1, string[] rgpszFile = {string[1]}, uint[] rggrfChange = {uint[1]}) Line 290 C#
What should I do to receive the event only once?
I got it to work by detaching the notifications in the method and re-attaching them at the end.
Looks something like this (note that I omitted some details regardingserviceProvider
, fileChangeCookie
, filesChanged
-array, ...)
int IVsFileChangeEvents.FilesChanged(uint numberOfFilesChanged, string[] filesChanged, uint[] flags)
{
IVsFileChangeEx fileChangeService = yourServiceProvider.GetService(typeof(SVsFileChangeEx));
// Detach from notifications
fileChangeService.UnadviseFileChange(GetCookieFromFile(filesChanged[0]));
// Do your stuff with the file
...
// Re-attach to notifications
fileChangeService.AdviseFileChange(filesChanged[0], (uint)(_VSFILECHANGEFLAGS.VSFILECHG_Time | _VSFILECHANGEFLAGS.VSFILECHG_Del), this, out fileChangeCookie);
}
I've had similar problems with the Win32-level file changed events. There are a lot of things you can to do reduce the problems (like disconnecting the events). In reality, you have no idea how many times a file might get "changed" during the handling of the event. For message-based events, all it takes is a call to anything that processes messages to get reentered, for multithreaded events, you don't even have to call something--it can happen no matter what you do. As a result, you should be very careful about what you do when you receive the notification. Ideally your event handler should be written in a way that it can handle being called again while it's still processing the previous event. Depending on what the dialog and subsequent processing does, you may be able to just keep track of whether or not it is open and/or processing and ignore any concurrent events, or you may need to notify the dialog or processing code that another change has occurred. Disconnecting and reconnecting the notifications works for message-based events, but not if there is any threading going on.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With