The default implementation of the ActionMessage.PrepareContext does not enforce thread affinity whenever an action guard changes:
```
PropertyChangedEventHandler handler = null;
handler = (s, e) =>
{
if (string.IsNullOrEmpty(e.PropertyName) || e.PropertyName == guardName)
{
if (context.Message == null)
{
inpc.PropertyChanged -= handler;
return;
}
context.Message.UpdateAvailability();
}
};
```
If a guard changes as a consequence of an asynchronous operation, this line
```
context.Message.UpdateAvailability();
```
will try to manipulate a DependencyObject, throwing an exception.
Wrapping such call into an Execute.OnUIThread seems to me the best approach, considering that property change notification are often silently marshalled on the UI thread (consider the Binding mechanism).
Note that such modification can be implemented as a customization, nevertheless I think that the current approach bears no benefits, while changing the default implementation causes no harm.
Comments: Changed with [5f4e82b41769](https://caliburnmicro.codeplex.com/SourceControl/changeset/5f4e82b41769). It is a little different than your proposed fix, as I don't want to transition to the UI thread when the event is not raised for the guard property. May you stress-test this version again, please.
```
PropertyChangedEventHandler handler = null;
handler = (s, e) =>
{
if (string.IsNullOrEmpty(e.PropertyName) || e.PropertyName == guardName)
{
if (context.Message == null)
{
inpc.PropertyChanged -= handler;
return;
}
context.Message.UpdateAvailability();
}
};
```
If a guard changes as a consequence of an asynchronous operation, this line
```
context.Message.UpdateAvailability();
```
will try to manipulate a DependencyObject, throwing an exception.
Wrapping such call into an Execute.OnUIThread seems to me the best approach, considering that property change notification are often silently marshalled on the UI thread (consider the Binding mechanism).
Note that such modification can be implemented as a customization, nevertheless I think that the current approach bears no benefits, while changing the default implementation causes no harm.
Comments: Changed with [5f4e82b41769](https://caliburnmicro.codeplex.com/SourceControl/changeset/5f4e82b41769). It is a little different than your proposed fix, as I don't want to transition to the UI thread when the event is not raised for the guard property. May you stress-test this version again, please.