dotnet/wpf · error · ArgumentException
SR.ContextMenuInDifferentDispatcher
Error message
SR.ContextMenuInDifferentDispatcher
What it means
ContextMenuService.GetContextMenu reads the ContextMenu attached property from an element and throws ArgumentException(SR.ContextMenuInDifferentDispatcher) when the retrieved menu is non-null but belongs to a different Dispatcher (i.e., was created on another UI thread). Cross-thread use of a DependencyObject is forbidden in WPF.
Solutions
- Create the ContextMenu on the same thread (Dispatcher) as the element it will be attached to.
- Marshal work back with element.Dispatcher.Invoke/BeginInvoke before reading or assigning the menu.
- Rebuild the menu on the target thread instead of sharing a single instance across threads.
- Check cm.Dispatcher == element.Dispatcher before calling GetContextMenu if the menu's origin is uncertain.
Example fix
// before var menu = ContextMenuService.GetContextMenu(element); // menu on other thread // after ContextMenu menu = null; element.Dispatcher.Invoke(() => menu = ContextMenuService.GetContextMenu(element));
Defensive patterns
Strategy: validation
Validate before calling
ContextMenu cm = (ContextMenu)element.GetValue(ContextMenuService.ContextMenuProperty); bool safe = cm == null || cm.Dispatcher == element.Dispatcher;
Type guard
static bool IsSameDispatcher(ContextMenu cm, DependencyObject el) => cm == null || cm.Dispatcher == el.Dispatcher;
Try / catch
try
{
var menu = ContextMenuService.GetContextMenu(element);
}
catch (ArgumentException)
{
// menu belongs to another Dispatcher; rebuild it on element's thread
} Prevention
- Create UI objects on the thread that owns the element
- Use Dispatcher.Invoke when touching objects across threads
- Avoid sharing ContextMenu instances between windows on different Dispatchers
When it happens
Trigger: Calling ContextMenuService.GetContextMenu(element) where element.GetValue(ContextMenuProperty) returns a ContextMenu whose Dispatcher differs from element.Dispatcher — typically the menu was created on another UI thread.
Common situations: Multi-UI-thread WPF apps (multiple windows each with own Dispatcher) where a ContextMenu instance created on one thread is assigned to an element on another, or shared resource dictionaries across threads.
Related errors
- Processing is disabled while the Dispatcher is in this…
- SR.CollectionView_MissingSynchronizationCallback
- SR.CurrentDispatcherNotFound
- SR.DispatcherHasShutdown
- SR.DispatcherProcessingDisabled
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/bea9705a3ff8327a.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/ContextMenuService.cs:43
typeof(ContextMenuService), // Owner
new FrameworkPropertyMetadata((ContextMenu)null,
FrameworkPropertyMetadataOptions.None));
/// <summary>
/// Gets the value of the ContextMenu property on the specified object.
/// </summary>
/// <param name="element">The object on which to query the ContextMenu property.</param>
/// <returns>The value of the ContextMenu property.</returns>
[AttachedPropertyBrowsableForType(typeof(DependencyObject))]
public static ContextMenu GetContextMenu(DependencyObject element)
{
ArgumentNullException.ThrowIfNull(element);
ContextMenu cm = (ContextMenu)element.GetValue(ContextMenuProperty);
if ((cm != null) && (element.Dispatcher != cm.Dispatcher))
{
throw new ArgumentException(SR.ContextMenuInDifferentDispatcher);
}
return cm;
}
/// <summary>
/// Sets the ContextMenu property on the specified object.
/// </summary>
/// <param name="element">The object on which to set the ContextMenu property.</param>
/// <param name="value">
/// The value of the ContextMenu property. If the value is of type ContextMenu, then
/// that is the ContextMenu that will be used (without any modification). If the value
/// is of any other type, then that value will be used as the content for a ContextMenu
/// provided by this service, and the other attached properties of this service
/// will be used to configure the ContextMenu.
/// </param>
public static void SetContextMenu(DependencyObject element, ContextMenu value)
{View on GitHub (pinned to 81131a70a4)