Skip to content

Commit 1b81904

Browse files
committed
Change loader notification processing to defer syncmacro call
1 parent da975ae commit 1b81904

File tree

3 files changed

+18
-12
lines changed

3 files changed

+18
-12
lines changed

Source/ExcelDna.IntelliSense/IntellisenseHelper.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public IntelliSenseHelper()
2525

2626
_providers = new List<IIntelliSenseProvider>
2727
{
28-
new ExcelDnaIntelliSenseProvider(),
28+
new ExcelDnaIntelliSenseProvider(_syncContextMain),
2929
new WorkbookIntelliSenseProvider(),
3030
};
3131

Source/ExcelDna.IntelliSense/Providers/ExcelDnaIntelliSenseProvider.cs

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -101,20 +101,24 @@ public IEnumerable<FunctionInfo> GetFunctionInfos()
101101
}
102102
}
103103

104-
ExcelSynchronizationContext _syncContextExcel;
105-
XmlIntelliSenseProvider _xmlProvider;
106-
Dictionary<string, XllRegistrationInfo> _xllRegistrationInfos = new Dictionary<string, XllRegistrationInfo>();
104+
readonly SynchronizationContext _syncContextMain; // Main thread, not macro context
105+
readonly ExcelSynchronizationContext _syncContextExcel; // Proper macro context
106+
readonly XmlIntelliSenseProvider _xmlProvider;
107+
readonly Dictionary<string, XllRegistrationInfo> _xllRegistrationInfos = new Dictionary<string, XllRegistrationInfo>();
107108
LoaderNotification _loaderNotification;
108109
bool _isDirty;
110+
SendOrPostCallback _processLoadNotification;
109111
public event EventHandler Invalidate;
110112

111-
public ExcelDnaIntelliSenseProvider()
113+
public ExcelDnaIntelliSenseProvider(SynchronizationContext syncContextMain)
112114
{
113115
_loaderNotification = new LoaderNotification();
114116
_loaderNotification.LoadNotification += loaderNotification_LoadNotification;
117+
_syncContextMain = syncContextMain;
115118
_syncContextExcel = new ExcelSynchronizationContext();
116119
_xmlProvider = new XmlIntelliSenseProvider();
117120
_xmlProvider.Invalidate += (sender, e) => OnInvalidate(null);
121+
_processLoadNotification = ProcessLoadNotification;
118122
}
119123

120124
#region IIntelliSenseProvider implementation
@@ -188,19 +192,17 @@ public IList<FunctionInfo> GetFunctionInfos()
188192
// TODO: Consider Load/Unload done when AddIns is enumerated...
189193
void loaderNotification_LoadNotification(object sender, LoaderNotification.NotificationEventArgs e)
190194
{
191-
// Debug.Print($"@>@>@>@> LoadNotification: {e.Reason} - {e.FullDllName}");
195+
Debug.Print($"@>@>@>@> LoadNotification: {e.Reason} - {e.FullDllName}");
192196
if (e.FullDllName.EndsWith(".xll", StringComparison.OrdinalIgnoreCase))
193-
_syncContextExcel.Post(ProcessLoadNotification, e);
197+
_syncContextMain.Post(_processLoadNotification, e);
194198
}
195199

196-
// Runs on the main thread, in a macro context
200+
// Runs on the main thread, but not in a macro context
197201
// WARNING: The sequence of calls here, between queued
198202
// instances of ProcessLoadNotification, Refresh and OnInvalidate
199203
// is quite fragile.
200204
void ProcessLoadNotification(object state)
201205
{
202-
Debug.Assert(Thread.CurrentThread.ManagedThreadId == 1);
203-
// we might want to introduce a delay here, so that the .xll can complete loading...
204206
var notification = (LoaderNotification.NotificationEventArgs)state;
205207
var xllPath = notification.FullDllName;
206208

@@ -222,7 +224,9 @@ void ProcessLoadNotification(object state)
222224
if (!_isDirty)
223225
{
224226
_isDirty = true;
225-
_syncContextExcel.Post(OnInvalidate, null);
227+
// This call would case trouble while Excel is shutting down.
228+
// CONSIDER: Is there a check we might do.... (and do we in fact get .xll loads during shutdown?)
229+
_syncContextExcel.Post(OnInvalidate, null);
226230
}
227231

228232
}
@@ -259,8 +263,10 @@ IEnumerable<string> GetLoadedXllPaths()
259263
}
260264
}
261265

266+
// Must be called on the main thread, in a macro context
262267
void OnInvalidate(object _unused_)
263268
{
269+
Debug.Assert(Thread.CurrentThread.ManagedThreadId == 1);
264270
Invalidate?.Invoke(this, EventArgs.Empty);
265271
}
266272

Source/ExcelDna.IntelliSense/UIMonitor/WindowWatcher.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ bool UpdateFocus(IntPtr windowHandle, string windowClassName)
136136
{
137137
if (windowHandle == _focusedWindowHandle)
138138
{
139-
Debug.Assert(_focusedWindowClassName == windowClassName);
139+
Debug.Assert(_focusedWindowClassName == windowClassName); // I've seen this, with _focusedWindowClassName == "" and windowClassName == "EXCEL7".
140140
return false;
141141
}
142142

0 commit comments

Comments
 (0)