Unreachable Code Warning in Static EventHandler callback - c#

We have an interesting issue occurring that I wonder if anyone may be able to shed light on. We are currently seeing the warning: "Method never reaches end or 'return' statement" on an event handler delegate callback that is rather odd.
Consider the following code (you can ignore the SCB_ functions, they are not relevant to the question):
public static class NativeBridge
{
private static UnityEventQueue _eventQueue;
private static bool _initialized;
public static void Init()
{
if (_initialized)
{
return;
}
_initialized = true;
SCB_SDKInit();
_eventQueue = UnityEventQueue.Instance;
_eventQueue.AppExiting += EventQueue_AppExiting;
SCB_registerReceivedSistrCallback(SistrReceived);
}
//Lots of other irrelevant code
private static void EventQueue_AppExiting(object sender, EventArgs e)
{
SCB_registerReceivedSistrCallback(null);
_eventQueue.AppExiting -= EventQueue_AppExiting;
SCB_SDKFinal();
_initialized = false;
}
}
The warning is on EventQueue_AppExiting. Here is the odd part. If I comment out the unregistration, _eventQueue.AppExiting -= EventQueue_AppExiting, the warning disappears.
We have tried a variety of "solutions" for what seems like a bug in the unreachability pass of the compiler:
Make the static class, non-static and adjust accordingly
Make the event in UnityEngineQueue static, and adjust accordingly
Place the event un-registration at the end of the callback method
Comment out the calls to the void SCB_ functions to sanity check
Various other Spaghetti at the wall solutions
All of the above yielded no change in the compiler's behavior. Our best guess is that the compiler detects the unregistration and thinks that because the delegate is removed, that it cannot complete execution at runtime, even though I believe the stack would have to continue execution even after removal because the invocation had already begun.
It does not seem like this is having any adverse effect in the application's execution, however it is difficult to debug due to the nature of the event's invocation conditions (Application Exiting).
What could the complier be seeing and/or what are we potentially doing wrong?
P.S.
For a bit of context, the class is static because it acts as an extern bridge to various platform specific libraries with a similar API. But that fact has little to do with the question, just to quell the "EWWWW Static Class" sentiment.

I think it is a bug as reported on this link:
https://bugzilla.xamarin.com/show_bug.cgi?id=42819
and here
https://bugzilla.xamarin.com/show_bug.cgi?id=41798
They report as fixed in version 6.2.0.259

Related

c# - Why does this paint handler loop many times? [duplicate]

When I create a new project, I get a strange behavior for unhandled exceptions. This is how I can reproduce the problem:
1) create a new Windows Forms Application (C#, .NET Framework 4, VS2010)
2) add the following code to the Form1_Load handler:
int vara = 5, varb = 0;
int varc = vara / varb;
int vard = 7;
I would expect that VS breaks and shows an unhandled exception message at the second line. However, what happens is that the third line is just skipped without any message and the application keeps running.
I don't have this problem with my existing C# projects. So I guess that my new projects are created with some strange default settings.
Does anyone have an idea what's wrong with my project???
I tried checking the boxes in Debug->Exceptions. But then executions breaks even if I handle the exception in a try-catch block; which is also not what I want. If I remember correctly, there was a column called "unhandled exceptions" or something like this in this dialog box, which would do excatly what I want. But in my projects there is only one column ("Thrown").
This is a nasty problem induced by the wow64 emulation layer that allows 32-bit code to run on the 64-bit version of Windows 7. It swallows exceptions in the code that runs in response to a notification generated by the 64-bit window manager, like the Load event. Preventing the debugger from seeing it and stepping in. This problem is hard to fix, the Windows and DevDiv groups at Microsoft are pointing fingers back and forth. DevDiv can't do anything about it, Windows thinks it is the correct and documented behavior, mysterious as that sounds.
It is certainly documented but just about nobody understands the consequences or thinks it is reasonable behavior. Especially not when the window procedure is hidden from view of course, like it is in any project that uses wrapper classes to hide the window plumbing. Like any Winforms, WPF or MFC app. Underlying issue is Microsoft could not figure out how to flow exceptions from 32-bit code back to the 64-bit code that triggered the notification back to 32-bit code that tries to handle or debug the exception.
It is only a problem with a debugger attached, your code will bomb as usual without one.
Project > Properties > Build tab > Platform target = AnyCPU and untick Prefer 32-bit. Your app will now run as a 64-bit process, eliminating the wow64 failure mode. Some consequences, it disables Edit + Continue for VS versions prior to VS2013 and might not always be possible when you have a dependency on 32-bit code.
Other possible workarounds:
Debug > Exceptions > tick the Thrown box for CLR exceptions to force the debugger to stop at the line of code that throws the exception.
Write try/catch in the Load event handler and failfast in the catch block.
Use Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException) in the Main() method so that the exception trap in the message loop isn't disabled in debug mode. This however makes all unhandled exceptions hard to debug, the ThreadException event is pretty useless.
Consider if your code really belongs in the Load event handler. It is very rare to need it, it is however very popular in VB.NET and a swan song because it is the default event and a double-click trivially adds the event handler. You only ever really need Load when you are interested in the actual window size after user preferences and autoscaling is applied. Everything else belongs in the constructor.
Update to Windows 8 or later, they have this wow64 problem solved.
In my experience, I only see this issue when I'm running with a debugger attached. The application behaves the same when run standalone: the exception is not swallowed.
With the introduction of KB976038, you can make this work as you'd expect again. I never installed the hotfix, so I'm assuming it came as part of Win7 SP1.
This was mentioned in this post:
The case of the disappearing OnLoad exception – user-mode callback exceptions in x64
Here's some code that will enable the hotfix:
public static class Kernel32
{
public const uint PROCESS_CALLBACK_FILTER_ENABLED = 0x1;
[DllImport("Kernel32.dll")]
public static extern bool SetProcessUserModeExceptionPolicy(UInt32 dwFlags);
[DllImport("Kernel32.dll")]
public static extern bool GetProcessUserModeExceptionPolicy(out UInt32 lpFlags);
public static void DisableUMCallbackFilter() {
uint flags;
GetProcessUserModeExceptionPolicy(out flags);
flags &= ~PROCESS_CALLBACK_FILTER_ENABLED;
SetProcessUserModeExceptionPolicy(flags);
}
}
Call it at the beginning of your application:
[STAThread]
static void Main()
{
Kernel32.DisableUMCallbackFilter();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
I've confirmed (with the the simple example shown below) that this works, just as you'd expect.
protected override void OnLoad(EventArgs e) {
throw new Exception("BOOM"); // This will now get caught.
}
So, what I don't understand, is why it was previously impossible for the debugger to handle crossing kernel-mode stack frames, but with this hotfix, they somehow figured it out.
As Hans mentions, compile the application and run the exe without a debugger attached.
For me the problem was changing a Class property name that a BindingSource control was bound to. Running without the IDE I was able to see the error:
Cannot bind to the property or column SendWithoutProofReading on the
DataSource. Parameter name: dataMember
Fixing the BindingSource control to bind to the updated property name resolved the problem:
I'm using WPF and ran into this same problem. I had tried Hans 1-3 suggestions already, but didn't like them because studio wouldn't stop at where the error was (so I couldn't view my variables and see what was the problem).
So I tried Hans' 4th suggestion. I was suprised at how much of my code could be moved to the MainWindow constructor without any issue. Not sure why I got in the habit of putting so much logic in the Load event, but apparently much of it can be done in the ctor.
However, this had the same problem as 1-3. Errors that occur during the ctor for WPF get wrapped into a generic Xaml exception. (an inner exception has the real error, but again I wanted studio to just break at the actual trouble spot).
What ended up working for me was to create a thread, sleep 50ms, dispatch back to main thread and do what I need...
void Window_Loaded(object sender, RoutedEventArgs e)
{
new Thread(() =>
{
Thread.Sleep(50);
CrossThread(() => { OnWindowLoaded(); });
}).Start();
}
void CrossThread(Action a)
{
this.Dispatcher.BeginInvoke(a);
}
void OnWindowLoaded()
{
...do my thing...
This way studio would break right where an uncaught exception occurs.
A simple work-around could be if you can move your init code to another event like as Form_Shown which called later than Form_Load, and use a flag to run startup code at first form shown:
bool firstLoad = true; //flag to detect first form_shown
private void Form1_Load(object sender, EventArgs e)
{
//firstLoad = true;
//dowork(); //not execute initialization code here (postpone it to form_shown)
}
private void Form1_Shown(object sender, EventArgs e)
{
if (firstLoad) //simulate Form-Load
{
firstLoad = false;
dowork();
}
}
void dowork()
{
var f = File.OpenRead(#"D:\NoSuchFile756.123"); //this cause an exception!
}

Display custom warning at compile time related to method implementation in C#

In the current context we have two methods Start and Stop. These two methods are invoked from a function sequentially. There can be chances that a person invokes just Start() inside his method but forgets to invoke Stop(). e.g.
private void A()
{
Start();
//Buisness logic goes here
}
In this context when the code is compiled a warning or error needs to be displayed informing that for every Start() there should be a corresponding Stop(). Can somebody suggest ideas on how to go about implementing the same in C#?
The proper way of implementation would be
private void A()
{
Start();
//Buisness logic goes here
Stop();
}
I would suggest you change your pattern to take care of the Start and Stop without ever exposing it to the programmer.
Change your class implementing Start & Stop to implementing an Execute method instead and dont even expose the Start & Stop.
public class MyClass
{
private void Start(){} // old public method
private void Stop(){} // old public method
public void Execute(Action action)
{
Start();
action();
Stop();
}
}
Usage:
var impl = new MyClass();
impl.Execute(() => {
// do something in between start & stop
});
Evk gave a good hint, here is how I would do it in more detail:
Have a class (e.g. StartStop ) implement IDisposable
public class StartStop : IDisposable
{
public StartStop() { Start(); }
public void Dispose() { Stop(); }
protected void Start() { /*...*/ }
protected void Stop() { /*...*/ }
}
Make use of this class with using:
private void A()
{
using( var startStopCaller = new StartStopCaller() )
{
// Your code here
}
}
using will make sure Dispose() and subsequently Stop() will be called except for hard crashes.
This can be approached in many ways, with two primary directions:
If you're using the later versions of the .NET platform, and thus the Roslyn compiler (Defaults from VS2015 and onwards), you can look into writing a compiler plugin that checks this for you. Here are some resources:
Introduction to Scripting with the .NET Compiler Platform (Roslyn)
.NET Compiler Platform SDK
Probably a lot more out there, if you search for "Roslyn" or ".NET Compiler platform".
As some of the comments you got are pointing out, this could be fixed in your code and program design. This is most probably the "correct" way to approach this. Some examples:
Consider implementing IDisposable and use your class in a using statement - however, remember that stopping and disposing of an object might not be the same here. You should make an informed desicion about this with the knowledge you have about the inner workings of your program.
If you're calling these classes from elsewhere, you could let them implement an interface containing both your Start and Stop methods. And then let the calling class simply treat them as this interface, and make sure it calls both methods no matter which implementation it uses.
Re-architect your code to not depend upon running Start() and Stop() sequentially. This might require fundamental design changes to your program and how it works, but it might just be worth it. Both for readability and maintainability.

why does the instance method Controls.Find crash without an exception? [duplicate]

When I create a new project, I get a strange behavior for unhandled exceptions. This is how I can reproduce the problem:
1) create a new Windows Forms Application (C#, .NET Framework 4, VS2010)
2) add the following code to the Form1_Load handler:
int vara = 5, varb = 0;
int varc = vara / varb;
int vard = 7;
I would expect that VS breaks and shows an unhandled exception message at the second line. However, what happens is that the third line is just skipped without any message and the application keeps running.
I don't have this problem with my existing C# projects. So I guess that my new projects are created with some strange default settings.
Does anyone have an idea what's wrong with my project???
I tried checking the boxes in Debug->Exceptions. But then executions breaks even if I handle the exception in a try-catch block; which is also not what I want. If I remember correctly, there was a column called "unhandled exceptions" or something like this in this dialog box, which would do excatly what I want. But in my projects there is only one column ("Thrown").
This is a nasty problem induced by the wow64 emulation layer that allows 32-bit code to run on the 64-bit version of Windows 7. It swallows exceptions in the code that runs in response to a notification generated by the 64-bit window manager, like the Load event. Preventing the debugger from seeing it and stepping in. This problem is hard to fix, the Windows and DevDiv groups at Microsoft are pointing fingers back and forth. DevDiv can't do anything about it, Windows thinks it is the correct and documented behavior, mysterious as that sounds.
It is certainly documented but just about nobody understands the consequences or thinks it is reasonable behavior. Especially not when the window procedure is hidden from view of course, like it is in any project that uses wrapper classes to hide the window plumbing. Like any Winforms, WPF or MFC app. Underlying issue is Microsoft could not figure out how to flow exceptions from 32-bit code back to the 64-bit code that triggered the notification back to 32-bit code that tries to handle or debug the exception.
It is only a problem with a debugger attached, your code will bomb as usual without one.
Project > Properties > Build tab > Platform target = AnyCPU and untick Prefer 32-bit. Your app will now run as a 64-bit process, eliminating the wow64 failure mode. Some consequences, it disables Edit + Continue for VS versions prior to VS2013 and might not always be possible when you have a dependency on 32-bit code.
Other possible workarounds:
Debug > Exceptions > tick the Thrown box for CLR exceptions to force the debugger to stop at the line of code that throws the exception.
Write try/catch in the Load event handler and failfast in the catch block.
Use Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException) in the Main() method so that the exception trap in the message loop isn't disabled in debug mode. This however makes all unhandled exceptions hard to debug, the ThreadException event is pretty useless.
Consider if your code really belongs in the Load event handler. It is very rare to need it, it is however very popular in VB.NET and a swan song because it is the default event and a double-click trivially adds the event handler. You only ever really need Load when you are interested in the actual window size after user preferences and autoscaling is applied. Everything else belongs in the constructor.
Update to Windows 8 or later, they have this wow64 problem solved.
In my experience, I only see this issue when I'm running with a debugger attached. The application behaves the same when run standalone: the exception is not swallowed.
With the introduction of KB976038, you can make this work as you'd expect again. I never installed the hotfix, so I'm assuming it came as part of Win7 SP1.
This was mentioned in this post:
The case of the disappearing OnLoad exception – user-mode callback exceptions in x64
Here's some code that will enable the hotfix:
public static class Kernel32
{
public const uint PROCESS_CALLBACK_FILTER_ENABLED = 0x1;
[DllImport("Kernel32.dll")]
public static extern bool SetProcessUserModeExceptionPolicy(UInt32 dwFlags);
[DllImport("Kernel32.dll")]
public static extern bool GetProcessUserModeExceptionPolicy(out UInt32 lpFlags);
public static void DisableUMCallbackFilter() {
uint flags;
GetProcessUserModeExceptionPolicy(out flags);
flags &= ~PROCESS_CALLBACK_FILTER_ENABLED;
SetProcessUserModeExceptionPolicy(flags);
}
}
Call it at the beginning of your application:
[STAThread]
static void Main()
{
Kernel32.DisableUMCallbackFilter();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
I've confirmed (with the the simple example shown below) that this works, just as you'd expect.
protected override void OnLoad(EventArgs e) {
throw new Exception("BOOM"); // This will now get caught.
}
So, what I don't understand, is why it was previously impossible for the debugger to handle crossing kernel-mode stack frames, but with this hotfix, they somehow figured it out.
As Hans mentions, compile the application and run the exe without a debugger attached.
For me the problem was changing a Class property name that a BindingSource control was bound to. Running without the IDE I was able to see the error:
Cannot bind to the property or column SendWithoutProofReading on the
DataSource. Parameter name: dataMember
Fixing the BindingSource control to bind to the updated property name resolved the problem:
I'm using WPF and ran into this same problem. I had tried Hans 1-3 suggestions already, but didn't like them because studio wouldn't stop at where the error was (so I couldn't view my variables and see what was the problem).
So I tried Hans' 4th suggestion. I was suprised at how much of my code could be moved to the MainWindow constructor without any issue. Not sure why I got in the habit of putting so much logic in the Load event, but apparently much of it can be done in the ctor.
However, this had the same problem as 1-3. Errors that occur during the ctor for WPF get wrapped into a generic Xaml exception. (an inner exception has the real error, but again I wanted studio to just break at the actual trouble spot).
What ended up working for me was to create a thread, sleep 50ms, dispatch back to main thread and do what I need...
void Window_Loaded(object sender, RoutedEventArgs e)
{
new Thread(() =>
{
Thread.Sleep(50);
CrossThread(() => { OnWindowLoaded(); });
}).Start();
}
void CrossThread(Action a)
{
this.Dispatcher.BeginInvoke(a);
}
void OnWindowLoaded()
{
...do my thing...
This way studio would break right where an uncaught exception occurs.
A simple work-around could be if you can move your init code to another event like as Form_Shown which called later than Form_Load, and use a flag to run startup code at first form shown:
bool firstLoad = true; //flag to detect first form_shown
private void Form1_Load(object sender, EventArgs e)
{
//firstLoad = true;
//dowork(); //not execute initialization code here (postpone it to form_shown)
}
private void Form1_Shown(object sender, EventArgs e)
{
if (firstLoad) //simulate Form-Load
{
firstLoad = false;
dowork();
}
}
void dowork()
{
var f = File.OpenRead(#"D:\NoSuchFile756.123"); //this cause an exception!
}

CallbackOnCollectedDelegate was detected on Walther MFS100 Check Scanner

i am trying to programming an interface for Walther Mfs100 Check scanner but after the scan i get "CallbackOnCollectedDelegate was detected" error. How can i fix this. I use .net 2.0 with c#
[DllImport("mflib.dll.stdcall")]
public static extern int mfScanFeeder(int mode, int font, int timeout);
retval = modMFS100.mfScanFeeder(0, 2,5000);
It isn't this particular API call that's the source of the problem. The API is too obscure and too poorly documented to give a straight answer, but look for an initialization style function that let's you set a callback. That callback is the cause of the exception. You must create a delegate object and store it in a field of your class. That way the garbage collector sees a reference to it and won't garbage collect it.
Thus, instead of:
void SetupScanner() {
mfInitialize(something, myCallback);
}
Do it like this:
SomeDelegateType callback;
void SetupScanner() {
callback = new SomeDelegateType(myCallback);
mfInitialize(something, callback);
}
Contact the vendor for support if this doesn't help.
Here is some info about this error:
http://social.msdn.microsoft.com/forums/en-US/Vsexpressvb/thread/665b876d-9070-41de-9a3a-d2093895d0c2
You can try to use static variable for your delegate, this will prevent the delegate from being garbage collected.

C# Am i using lock correctly?

I'm currently trying to write a thread-safe logger class. I'm not very familiar with correct design and best practices in this area. Is there a flaw in my code?
public class WriteStuff
{
private readonly StreamWriter m_Writer;
private readonly object m_WriteLock = new object ();
public WriteStuff(String path)
{
m_Writer = File.CreateText (path);
m_Writer.WriteLine ("x");
m_Writer.Flush ();
}
public void ListenTo(Foo foo)
{
foo.SomeEvent += new EventHandler<SomeArgs> (Foo_Update);
}
private void Foo_Update(object sender, SomeArgs args)
{
lock (m_WriteLock) {
m_Writer.WriteLine (args);
m_Writer.Flush ();
}
}
}
Well, that looks OK to me; I'd probably implement IDisposable as a means to Close() the file, but...
Of course, you could also use any of the (many) pre-canned logging frameworks.
Update:
One thought: you might want to consider what happens if the file already exists; you don't want to stomp on your logs...
What you've posted looks fine from a multi-threading perpective. Although I could be wrong, it would appear that any other code that does some multi-threading (even using the foo object) should be safe. Certainly, I can't see any deadlocks in the that section of code.
A few things worth noting anyway (apart from being very careful with deadlocks and testing rigourously to insure they won't occur):
It's best to put a lock around the code within the constructor, as I believe it's possible in certain circumstances that methods can be called before the constructor block has finished executing. (Someone please correct me if I'm wrong on this one.)
The StreamWriter object in this case is private, which is good. If it were protected or internal you would certainly have to be cautious about how other code utilised the object (in fact I think it would be best to almost always declare such objects as private).
You've done locking the right way! It's always safest to lock on a separate private instance object because you know that object can't be locked by any other code than your own (which isn't the case if you lock this or the StreamWriter object itself).
Still, I may be missing something, and there is a small possibility that some other code not shown above might cause problems, but as far as I can see it that code isn't flawed except for a possible missing lock around the constructor code. You're more likely to have to watch out for deadlock situations when you start doing more complex multi-threading, especially across classes/instances.
Anyway, hope that helps.
The event handler is on the same thread as the event generator which means your app could end up being held up by your log file write.
private void Foo_Update(object sender, SomeArgs args) {
ThreadPool.QueueUserWorkItem(WriteAsync, args);
}
private void WriteAsync(object state) {
SomeArgs args = (SomeArgs)state;
lock (m_WriteLock) {
m_Writer.WriteLine (args);
m_Writer.Flush ();
}
}

Categories

Resources