Display custom warning at compile time related to method implementation in C# - 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.

Related

Is there a way to handle the event when a new thread is created in the current process?

I want to able to detect when a new thread is created e.g. Task.Run and, if possible, handle when its closed.
I know it's possible to get the current threads being handled by your process via Process.GetCurrentProcess().Threads and that's somewhat useful. What I want though it's to handle when a new thread begin it's execution, from a perspective that I don't know where it's been created.
Some background
As it was asked, I'm putting here some detail to the actual problem I'm running into, because maybe I'm searching for the least optimal solution.
I'm developing a large system with multiple screen, each one with a bunch of controls, which some of them are custom. Recently, the team has gradually been adopting async/await patterns and the issue of locking the UI untill a task is completed has risen. We created a loading panel in our base form, exposing a hide and show method to be called by the implementations of this base form. The problem here is returning to all those forms that are already implemented and placing calls to those methods throughout the code, especially async events. Here I wonder if there's an easier solution that will work for the past implementations and eliminate the need of calling methods between events.
What we are doing as in today, is something along the lines:
public class BaseForm {
public ShowPanel(){
...
}
public HidePanel(){
...
}
}
public class FormImplementation : BaseForm {
private async void OnEventAsync(object sender, EventArgs e){
ShowPanel();
// await stuff
HidePanel();
}
}
I find it to be quite cumbersome to manually place those calls around event handlers. I'd do some metaprogramming karate, but I'm not experienced with it in C#.
maybe I'm searching for the least optimal solution.
Examining threads is definitely an incorrect approach. For one, async doesn't use threads, so that approach would not have worked.
I find it to be quite cumbersome to manually place those calls around event handlers. I'd do some metaprogramming karate, but I'm not experienced with it in C#.
Metaprogramming is one option, and a pretty decent one. PostSharp and Fody are both highly regarded. The "do something at the beginning and end of these methods" is a common problem in that field, and metaprogramming is a definite option. I think what you actually want is something like this:
public class BaseForm {
public ShowPanel() {
...
}
public HidePanel() {
...
}
}
public class FormImplementation : BaseForm {
private async void OnEventAsync(object sender, EventArgs e) {
ShowPanel();
try { ... }
finally { HidePanel(); }
}
}
You can minimize the code changes by using a disposable, e.g., (using my Nito.Disposables library) with a C# 8 using declaration:
public class BaseForm {
public IDisposable ShowPanel() {
...
return new AnonymousDisposable(HidePanel);
}
private void HidePanel() {
...
}
}
public class FormImplementation : BaseForm {
private async void OnEventAsync(object sender, EventArgs e) {
using var _ = ShowPanel();
...
}
}
There are other alternatives, such as changing the return type of OnEventAsync to be Task, but that would require more code changes I think than just doing the above.

Unreachable Code Warning in Static EventHandler callback

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

c# static object reference

I have a class like so
public class FileLogger
{
public FileLogger(string typeOfLog)
{
//implementation
}
public void LogError(string err)
{
//implementation
}
public void LogMessage(string err)
{
//implementation
}
}
Since this is a logging class for an application to log its output to a file, one would have expected it to be a static class. However as you can see it is not. It is however used in the application like this:
public class BugetApplication
{
private static FileLogger logger;
//constructor
public BugetApplicationClass()
{
logger = new FileLogger("some-constructor-parameter");
}
//a method that uses the FileLogger class for logging
public string Classify()
{
try
{
//start multiple threads for classification
Classification clsf = new Classification();
clsf.handleEvent += clsf_handleEvent;
clsf.Classify();
}
catch (Exception exp)
{
logger.LogError(exp.Message);
}
}
private static void clsf_handleEvent(string errString)
{
if(errString.Contains("error"))
{
logger.LogError(errString);
}
}
}
Multiple threads are started by the BugetApplication class's classify method. Any errors in that class fire an event which is handled in the BugetApplication class's clsf_handleEvent method. So multiple threads could each fire their own event. Would creating the instance variable as a static variable in the BugetApplication class have any effect here or would keeping it non static have the same effect? I don't want any one thread to overwrite the error message of another thread.
Edit
Just to clear things out, the BugetApplication class which will be created only once has a static variable 'static FileLogger logger; ' it creates an instance once in its constructor, passing in some values to the constructor of the FileLogger class. In the BugetApplication class, there is a method which calls the Classification class's classify method. The Classify method starts the various threads and on any error fires an event which is handled back in the BugetApplication class so this clsf_handleEvent method can have multiple calls on it.
Why do you think it would overwrite the error message of another thread? The logger should just append the messages, so there shouldn't be any overwriting (depends how you handle the logging though). There is a potential problem however - depending on your logging function you might be blocking access to the file. Because the method works on an external file, you should probably use lock in the function.
It really doesn't matter if the class is static or not, the problem is concurrent access to external resources which needs to be synchronized for multiple threads to become thread-safe.
lock documentation on msdn
It really depends on the actual implementation of the logger.
Static classes are now frowned upon as they make unit testing more difficult. Many facilities which conventionally were implemented as static or singleton (loggers, e-mailers, etc.) now provide unit test/IoC friendly alternatives (e.g. a factory and an interface or virtual class).
The design of these facilities is usually a front end class which the client application uses to interact and an asynchronous back end which takes care of the synchronization and actual logging (or emailing, or whatever).
The crux is whether the front ends are multi-threaded or not.
If they are not; you should create a new one per thread. In this case the logger would probably have to be a local variable or parameter of the method using it.
Usually, however, they are multi-threaded and re-entrant, as all they do is pass along the log message to the back-end and have no state of their own. In this case they can be saved as a static variable or application wide singleton, but it is better to instantiate them in an IoC container as singleton and inject it to the classes using them. Doing so makes writing unit tests with mock loggers a lot easier.

Debugging exceptions in a Async/Await (Call Stack)

I use the Async/Await to free my UI-Thread and accomplish multithreading. Now I have a problem when I hit a exception. The Call Stack of my Async parts allways starts with ThreadPoolWorkQue.Dipatch(), which doesn't help me very much.
I found a MSDN-Article Andrew Stasyuk. Async Causality Chain Tracking about it but as I understand it, its not a ready to use solution.
What is the best/easiest way to debug if you use multithreading with Async/Await?
The article you found does a good job of explaining why call stacks don't work the way most of us think they do. Technically, the call stack only tells us where the code is returning to after the current method. In other words, the call stack is "where the code is going", not "where the code came from".
Interestingly, the article does mention a solution in passing, but doesn't expound on it. I have a blog post that goes explains the CallContext solution in detail. Essentially, you use the logical call context to create your own "diagnostic context".
I like the CallContext solution better than the solution presented in the article because it does work will all forms of async code (including fork/join code like Task.WhenAll).
This is the best solution I know of (other than doing something really complex like hooking into the profiling API). Caveats of the CallContext approach:
It only works on .NET 4.5 full. No support for Windows Store apps, .NET 4.0, etc.
You do have to "instrument" your code manually. There's no way AFAIK to inject it automatically.
Exceptions don't capture the logical call context automatically. So this solution works fine if you're breaking into the debugger when exceptions are thrown, but it's not as useful if you're just catching the exceptions in another place and logging them.
The code (depends on the immutable collections NuGet library):
public static class MyStack
{
private static readonly string name = Guid.NewGuid().ToString("N");
private static ImmutableStack<string> CurrentContext
{
get
{
var ret = CallContext.LogicalGetData(name) as ImmutableStack<string>;
return ret ?? ImmutableStack.Create<string>();
}
set
{
CallContext.LogicalSetData(name, value);
}
}
public static IDisposable Push([CallerMemberName] string context = "")
{
CurrentContext = CurrentContext.Push(context);
return new PopWhenDisposed();
}
private static void Pop()
{
CurrentContext = CurrentContext.Pop();
}
private sealed class PopWhenDisposed : IDisposable
{
private bool disposed;
public void Dispose()
{
if (disposed)
return;
Pop();
disposed = true;
}
}
// Keep this in your watch window.
public static string CurrentStack
{
get
{
return string.Join(" ", CurrentContext.Reverse());
}
}
}
Usage:
static async Task SomeWorkAsync()
{
using (MyStack.Push()) // Pushes "SomeWorkAsync"
{
...
}
}
Update: I released a NuGet package (described on my blog) that uses PostSharp to inject the pushes and pops automatically. So getting a good trace should be a lot simpler now.

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