It sounds a little weird, but I've got some code (which actually is a plugin for MS Blend) that runs perfect in unit testing, but is not working within Blend.
The code is the following.
private static volatile QWGUIRepository s_instance;
public static void Initialize(IUnityContainer container, string themeuri)
{
lock (s_lock)
{
s_instance = new QWGUIRepository();
QWRepository.Initialize(container);
}
}
In the debugger (after attaching it to Blend), I can see that s_instance gets initialized with a value (is not null afterwards), however as soon as I get out of the method "s_instance" will forget it's value and will be null.
Any ideas?
Thanks,
Andreas
Two guesses:
1) You're reading in a different AppDomain than you're writing in. Static variables are scoped by AppDomain. If you look at AppDomain.CurrentDomain in the debugger during Initialize and then when you're trying to read it, does it look like they're the same domain?
2) You've actually declared s_instance to be a local variable in Initialize, and aren't touching the static variable. Hopefully that's not the case, but you never know...
I don't know anything about Blend, so this is a wild guess. Does Blend start the plugins in separate AppDomains? You can check that in the debug location toolbar in Visual Studio. That could explain it...
thanks for suggestions. Unfortunately (as usual) it was personal stupidity...
The answer is - make sure you only use strong-named assemblies.
Andreas
Related
I have some arbitrary code. e.g. the following:
class MyClass
{
private MyClass() { }
public static readonly MyClass Instance = new MyClass();
public Hashtable DoSomething() {return new Hashtable {{"key", "value"}};}
}
var test = MyClass.Instance.DoSomething();
Now when debugging and hovering test intellisense doesn´t show anything at all. Also adding a watch to the variable does not work. Instead the message
The name 'test' does not exist in the current context
appears. I already rebuilt the solution, closed VS and re-opened it. However when NOT debugging I get type-information on that variable within intellisense.
NB: Unfortunetaly the code above works within my test-solution, however the actual code which is far more complex does not. I already tried to simplify this as much as I can, supposing some downvotes as the error is hardly to reproduce. However maybe anyone has had a similar problem on VS.
EDIT: Optimization of code is disabled within projects settings (Properties-->Build-->optimize code)
The compiler most likely optimizes the variable away because it is never used locally.
Use the variable in any way to circumvent this:
var test = MyClass.Instance.DoSomething();
Debug.WriteLine(test); // <=== Set breakpoint here
I'm not 100% sure, but I think optimizations also affect this. So to be sure, turn them off if you have these problems.
This hit me recently on a project I was working on. Most people are familiar with property recursion:
public int Test
{
get { return this.test; }
set { this.Test = value; }
}
private int test;
You accidentally put an upper-case T in this setter, and you've opened yourself up to a StackoverflowException. What's worse is if you've not defined it, often visual studio will auto-correct the casing for you to the invalid state.
I did something similar however in a constructor recently:
public TestClass(int test)
{
this.Test = Test;
}
Unfortunately here you don't get a StackOverflowException, now you've got a programming error. In my case this value was passed to a WebService that instead used a default value (which wasn't 0) which caused me to miss the fact I had incorrectly assigned it. Integration tests all passed because this service didn't say
"Hey you forgot this really important field!"
What steps can I take to avoid this sort of behaviour? I've always been advised against defining variables like the following, and I don't like them personally, but I can't think of any other options:
private int _test;
private int mTest;
EDIT
Reasons that the underscore or m prefix are undesirable normally that I can think of are:
Readability
Slightly more difficult to scroll through members if you're inheriting from 3rd party classes as you get a mix of styles.
Best way is to use "Auto implemented properties" here.
public int Test { get; set; }
If not possible to use "Auto implemented properties" for some reason use _ prefix(I don't prefer though).
If you also don't prefer to use some prefixes, then you have other option. You don't have to write the property code by hand. Let the IDE do it for you; that way you can avoid careless mistakes. (I don't know how I missed this in original answer)
Just type
private int test;
Select the field, Right click Refactor->Encapsulate Field. IDE will generate property snippet for you as below.
public int Test
{
get { return test; }
set { test = value; }
}
You don't need to bother clicking the context menu. If you prefer keyboard, shortcut is Ctrl + R + E.
Or get a Resharper, It will point your silly mistake immediately.
Integration tests all passed
Then they weren't exhaustive enough tests. If there's an error that wasn't discovered by the tests, then you've got another test to write.
That's really the only automated solution here. The compiler isn't going to complain, because the code is structurally and syntactically correct. It's just not logically correct at runtime.
You can define naming standards, even use tools like StyleCop to attempt to enforce those standards. That would probably allow you to cover a lot, though it's not an ironclad solution and errors can still get through. Personally I agree with you that decorating variable names is unsightly in the code. Perhaps in some cases it's a valid tradeoff?
Ultimately, automated tests are your defense against these kinds of errors. At its simplest, if an error gets through your tests and into production then the response should be:
Write a test to reproduce the error.
Fix the error.
Use the test to validate the fix.
Granted, that only covers that one case, not every property definition in your code. But if this is happening a lot then you may have a personnel problem and not a technical problem. Somebody on the team is, well, sloppy. The solution to that problem may not be a technical one.
Use code snippets.
For every property backed by a private field, use a custom code snippet you have created, instead of writing it up from scratch or letting IntelliSense do the job (poorly).
After all, this problem is about conventions and discipline, rather than language design. The case sensitive nature of C# and the subperfect code completion in Visual Studio are the reason we make these mistakes, not our lack of knowledge and design.
You best bet here is to eliminate the chance of accidents and having a predefined way of writing these repetitive things correctly is the best way to go. It also is much more automated compared to remembering conventions and enforcing them by hand.
There is a default code snippet in Visual Studio for this. Type propfull and hit Tab, then specify the instance variable name and the property name and you're good to go.
In some cases you cannot get around setters and getters. But maybe you don't need the setters and getters if you follow the Tell, Don't Ask principle? It basically says to prefer having the object that has the data do the work, not some other object query a lot from the data object, make decisions, and then write data back to the data object. See http://martinfowler.com/bliki/TellDontAsk.html
Could you not just write a test to cover this?
int constructorValue = 4;
TestClass test = new TestClass(constructorValue);
Assert.Equals(test.Test, constructorValue);
You may not want to write tests immediately to cover yourself from future wobbles, but you've found a bug, why not protect yourself from it again?
For the record, if I need a private field to store the value for a pulic getter/setter, I always underscore it. There's just something an underscore that screams privacy!
public string Test
{
get { return _test; }
set { _test = value; }
}
private string _test;
I have stumbled across a situation where garbage collection seems to be behaving differently between the same code running written as a Unit Test vs written in the Main method of a Console Application. I am wondering the reason behind this difference.
In this situation, a co-worker and I were in disagreement over the effects of registering an event handler on garbage collection. I thought that a demonstration would be better accepted than simply sending him a link to a highly rated SO answer. As such I wrote a simple demonstration as a unit test.
My unit test showed things worked as I said they should. However, my coworker wrote a console application that showed things working his way, which meant that GC was not occurring as I expected on the local objects in the Main method. I was able to reproduce the behavior he saw simply by moving the code from my test into the Main method of a Console Application project.
What I would like to know is why GC does not seem to collecting objects as expected when running in the Main method of a Console Application. By extracting methods so that the call to GC.Collect and the object going out of scope occurred in different methods, the expected behavior was restored.
These are the objects I used to define my test. There is simply an object with an event and an object providing a suitable method for an event handler. Both have finalizers setting a global variable so that you can tell when they have been collected.
private static string Log;
public const string EventedObjectDisposed = "EventedObject disposed";
public const string HandlingObjectDisposed = "HandlingObject disposed";
private class EventedObject
{
public event Action DoIt;
~EventedObject()
{
Log = EventedObjectDisposed;
}
protected virtual void OnDoIt()
{
Action handler = DoIt;
if (handler != null) handler();
}
}
private class HandlingObject
{
~HandlingObject()
{
Log = HandlingObjectDisposed;
}
public void Yeah()
{
}
}
This is my test (NUnit), which passes:
[Test]
public void TestReference()
{
{
HandlingObject subscriber = new HandlingObject();
{
{
EventedObject publisher = new EventedObject();
publisher.DoIt += subscriber.Yeah;
}
GC.Collect(GC.MaxGeneration);
GC.WaitForPendingFinalizers();
Thread.MemoryBarrier();
Assert.That(Log, Is.EqualTo(EventedObjectDisposed));
}
//Assertion needed for foo reference, else optimization causes it to already be collected.
Assert.IsNotNull(subscriber);
}
GC.Collect(GC.MaxGeneration);
GC.WaitForPendingFinalizers();
Thread.MemoryBarrier();
Assert.That(Log, Is.EqualTo(HandlingObjectDisposed));
}
I pasted the body above in to the Main method of a new console application, and converted the Assert calls to Trace.Assert invocations. Both equality asserts fail then fail. Code of resulting Main method is here if you want it.
I do recognize that when GC occurs should be treated as non-deterministic and that generally an application should not be concerning itself with when exactly it occurs.
In all cases the code was compiled in Release mode and targeting .NET 4.5.
Edit: Other things I tried
Making the test method static since NUnit supports that; test still worked.
I also tried extracting the whole Main method into an instance method on program and calling that. Both asserts still failed.
Attributing Main with [STAThread] or [MTAThread] in case this made a difference. Both asserts still failed.
Based on #Moo-Juice's suggestions:
I referenced NUnit to the Console app so that I could use the NUnit asserts, they failed.
I tried various changes to visibility to the both the test, test's class, Main method, and the class containing the Main method static. No change.
I tried making the Test class static and the class containing the Main method static. No change.
If the following code was extracted to a separate method, the test would be more likely to behave as you expected. Edit: Note that the wording of the C# language specification does not require this test to pass, even if you extract the code to a separate method.
{
EventedObject publisher = new EventedObject();
publisher.DoIt += subscriber.Yeah;
}
The specification allows but does not require that publisher be eligible for GC immediately at the end of this block, so you should not write code in such a way that you are assuming it can be collected here.
Edit: from ECMA-334 (C# language specification) §10.9 Automatic memory management (emphasis mine)
If no part of the object can be accessed by any possible continuation of execution, other than the running of finalizers, the object is considered no longer in use and it becomes eligible for finalization. [Note: Implementations might choose to analyze code to determine which references to an object can be used in the future. For instance, if a local variable that is in scope is the only existing reference to an object, but that local variable is never referred to in any possible continuation of execution from the current execution point in the procedure, an implementation might (but is not required to) treat the object as no longer in use. end note]
The problem isn't that it's a console application - the problem is that you're likely running it through Visual Studio - with a debugger attached! And/or you're compiling the console app as a Debug build.
Make sure you're compiling a Release build. Then go to Debug -> Start Without Debugging, or press Ctrl+F5, or run your console application from a command line. The Garbage Collector should now behave as expected.
This is also why Eric Lippert reminds you not to run any perf benchmarks in a debugger in C# Performance Benchmark Mistakes, Part One.
The jit compiler knows that a debugger is attached, and it deliberately de-optimizes the code it generates to make it easier to debug. The garbage collector knows that a debugger is attached; it works with the jit compiler to ensure that memory is cleaned up less aggressively, which can greatly affect performance in some scenarios.
Lots of the reminders in Eric's series of articles apply to your scenario. If you're interested in reading more, here are the links for parts two, three and four.
While debugging I tried to save intermediate results of a calculation to a variable so that when a breakpoint condition is met I could check that value. However C# compiler (or CLR) optimized away that variable as unused. I solved the problem by making the variable a public field of the class, however I'd like to know if there is a straightforward solution to this problem.
"Optimize code" checkbox is unchecked. The build configuration is Debug.
Edit: Found that it only affects some unused variables in iterators that would normally end up as fields in the automatically generated iterator class; unused variables that are scoped within blocks not containing yield statements are retained.
The lazy option would be.... use the value, ideally in a way that doesn't allow it to be held on the stack. For example:
var tmp = SomeMethod();
// your other code
Debug.WriteLine(tmp);
the use of the value as an argument means it must be retained, but that line is automatically not compiled into release builds.
However! I must emphasize that locals are pretty-much always retained in an unoptimized/debug build, so I'm finding the scenario from the question hard to envisage.
If you are using Visual Studio, why not just add a breakpoint on the line following the line on which the calculation is being made, and then you can simply hover over the calculation to see the result in the intellisense/tooltip popup? I also think that you can add the calculation to the "watch" screen and view the result that way as well.
This is usually how I view the results of things I am debugging. Alternatively, you could just use the temp variable you created in some simple way to avoid getting the warning.
For example:
Console.Write(tempVariable);
Handy utility:
using static _globals;
static class _globals
{
[MethodImpl(MethodImplOptions.NoInlining), DebuggerHidden]
public static void Nop<T>(out T x) => x = default(T);
};
class Program
{
static void Main()
{
int i; // unreferenced variable
/// ...
Nop(out i);
/// ...
}
};
You need uncheck options "Optimize code" in project options for Debug build.
In my case "Optimize code" option was unchecked, still I was facing this issue. I checked it, build project then unchecked it and buid project again. This fixed issue for me.
For some time now, I've observed an intermittent COM problem in my VSIX package for Visual Studio 2010. Attempting to subscribe to one of the IDE's COM-based event sinks randomly throws the following error:
"COM object that has been separated from its underlying RCW cannot be used"
A repro case boils down to this code (which must be used in VSIX, obviously):
using System;
using EnvDTE;
using EnvDTE80;
class Test
{
private readonly Events _events;
private readonly Events2 _events2;
private readonly BuildEvents _buildEvents;
private readonly ProjectItemsEvents _projectItemsEvents;
public Test(IServiceProvider provider)
{
var dte = (DTE)provider.GetService(typeof(DTE));
var dte2 = (DTE2)dte;
// Store all references in fields as a GC precaution.
_events = dte.Events;
_events2 = (Events2)dte2.Events;
_buildEvents = _events.BuildEvents;
_projectItemsEvents = _events2.ProjectItemsEvents;
// Proceed to subscribe to event sinks.
_buildEvents.OnBuildBegin += BuildBeginHandler; // BOOM!
_projectItemsEvents.ItemAdded += ItemAddedHandler;
}
private void ItemAddedHandler(ProjectItem projectItem) { }
private void BuildBeginHandler(vsBuildScope scope, vsBuildAction action) { }
}
I've learned about a possible cause from numerous descriptions of similar problems that can be found on the net. It's basically a side effect of the way Runtime Callable Wrappers and GC interact during COM interop. Here's a link to a similar problem complete with explanation.
I'm fine with that explanation, especially because it suggests an easy workaround - storing the event sink reference in a field in order to prevent it from being prematurely GC'ed. Indeed, many people seem to have solved their problem this way.
What bothers me is that it doesn't work in my case. I'm really stumped as to why. As you can plainly see, I already store all object references in fields as a precaution. Yet the error still occurs. I tried being even more explicit using GC.KeepAlive() calls at the end of the ctor, but to no avail. Is there anything else left to do?
Without a solution, my VSIX randomly fails to load, leaving the user with a single option: to restart Visual Studio and hope it doesn't happen the next time.
Any help will truly be appreciated!
Well, I gave up and simply did the only thing that crossed my mind. I figured that since this is obviously a race condition I can't affect in a predictable manner, I might as well reenter the race if I lose.
So I moved the subscription lines into a while loop that try..catch-es them and retries after a bit of Thread.Sleep(). The loop exits either when both subscriptions succeed or when I've been continuously losing the race for more than 2 seconds.
The kicker is, I haven't lost the race once since I've implemented the change. A true Heisenbug, if I ever saw one.
Anyway, I'm going to stick with this until a proper solution occurs to me or the bug reappears.
I suspect that your problem is really that you are attempting to wire up your event handlers too soon. You normally need to be doing these sorts of things in the Initialize method of your package / toolwindow / whatever - generally speaking if you need to use a service you need to do if after the Initialize method has been called, definitely don't do this in the constructor of your Package.
(This is just a hunch - your Test class doesn't implement any VSX interfaces and so I can't see from your sample when the constructor is being called)