Description
Library produces unexpected side effects when listening to the DeviceFound
event and the event handler manipulates the UI. See Stack overflow post for details.
Since ALL exceptions are swallowed by an empty catch block (at least in the DeviceLocator
class), the client code shows unexpected behavior in case of an exception, as it continues to execute in an unpredictable state. In case of the event handler is accessing the UI, a cross thread exception is expected to be thrown by the .Net framework.
The library should either let the exception reach the client code or/and marshal the event handler execution to the UI thread, by raising the even on the dispatcher: Application.Current.Dispatcher.InvokeAsync(() => OnDeviceFound?.Invoke(null, new DeviceFoundEventArgs(device)));
. DeviceLocator
line 154.
A library should never swallow exceptions as this can lead to unexpected side effects. The client must be given the choice to decide and handle exceptions individually.
Check library for more occurrences.
Expected behavior
The library should either let the exception reach the client code or/and marshal the event handler execution to the UI thread, by raising the even on the dispatcher: Application.Current.Dispatcher.InvokeAsync(() => OnDeviceFound?.Invoke(null, new DeviceFoundEventArgs(device)));
Environment:
- OS: Windows
- WPF
Issue Analytics
- State:
- Created 4 years ago
- Comments:16 (16 by maintainers)
Hi @roddone, thanks for your reply. I deleted my previous post myself, as I got the feeling that I went too far and may have annoyed both of you. Maybe I was wrong. But I apologize for criticizing too much though. But this wasn’t arrogance, I can assure you 😳 Just passion. I love my business and that’s why I wanted to improve something, even if it doesn’t belong to me. I mean for some reason I came by to open this ticket. Absolutely no bad intention. I really like your project. Lots of people find it useful and use it. You guys obviously did a good job.
C# 8 has some nice features. But I’ve read that they won’t be all available in future .Net Framework releases as they would need to require runtime changes, which would break backward compatibility. We should always try to target at least .Net Standard 2.1+ for future projects in order to get the latest API and language features, but only if we don’t have to remain compatible with the .Net Framework.
I personally think that your project is destined to run in a .Net Core runtime or Mono if you like to be available e.g. on Xamarin platforms too. If you don’t depend on .Net Framework, you should do the step. But I wouldn’t mix code by introducing compiler directives to switch execution paths. I would do a clean separation and introduce new assemblies, where each targets a different runtime or platform. Generally, if I want to support .Net Framework and .Net Core I would create three assemblies. The first accumulates standardized cross-platform features e.g. by targeting .Net Standard 2.0. This will be the dependency for all other platforms as they will build upon it. Then the other two will target .Net Framework and .Net Core. They may differ in features and implementation details. I don’t know how realistic this is for you, as it will introduce some extra effort to maintain the library. But it would lever usability and flexibility as users could now run it on Linux machines too. So the user can decide which package he would like to install to target a specific platform. But it’s a matter of taste and just my opinion. I think Microsoft simplest recommendation on how to target multiple platforms is exactly the way you’ve described using preprocessor directives.
My private opinion is you should completely remove the event-driven API. I really like the idea of using
Progress<T>
. @thoemmi It’s perfect, because it internally marshals the callback execution back to the caller’s thread. The caller must create an instance ofProgress<T>
. The constructor captures the currentSynchroinizationContext
. Whenever and on whatever thread the registered callback is invoked, it will execute on this very captured context. You were absolutely right not to introduce a dependency on a specific UI platform (whatDispatcher
apparently would do). Application could run in a console application or as a service, indeed.Progress<T>
will solve this. I mean you could simply implement the context capturing yourself, but why worry. Very good idea 👍 I like 😃Hi! Don’t worry. I really hope that we all stay healthy and don’t experience any complications. All the best for you and your families. And take care for your neighbors too. Hope to see you very soon 😃