Constructor strange behavior - c#

I'm using third party library and I found a strange behavior of class constructor. This library is compiled for .NET Framework 4.5. Here is the minimalistic part of class from this library.
public class TokenFile
{
private readonly FileInfo _fileInfo;
private readonly object _lock;
private TokenState _tokenState;
public TokenFile(string filePath, object #lock)
{
_lock = #lock ?? throw new ArgumentNullException(nameof(#lock));
_fileInfo = new FileInfo(filePath);
_tokenState = TokenState.Disconnected;
}
/// <summary>
/// Indicates the current token state.
/// </summary>
public TokenState TokenState
{
get
{
lock (_lock)
{
return _tokenState;
}
}
set
{
lock (_lock)
{
_tokenState = value;
}
}
}
}
This is sample call for testing purposes.
public class TokenFileTest
{
void Test()
{
var tokenFile = new TokenFile(#"C:\Some\Path.txt", null);
var tokenState = tokenFile.TokenState;
}
}
I expect the ArgumentNullException at var tokenFile = new ... line.
But on several computers I get NullReferenceException at the next line.
Variable tokenFile is not null, but is not correctly initialized. All fields and properties are null.
On my computer everything works as expected.
When I create my own library with original code compiled for .NET Framework 4.8 everything works as expected on all computers.
Can anybody explain me what is wrong?
EDIT: TokenFile class sample updated

Related

How to test object that pushes values to using Reactive Extensions via `Sample` method

I have a class called ValuePusher with a property named Value and receives a dependency of type ValueReceiver, also with a property named Value. The former class arranges to 'push' values to an instance of the latter class via a System.Reactive.Subjects.Subject<int> object. Initially it pushes values one for one, but later it will restrict the amount of values pushed using the Sample method - note the commented-out call to this method in the code below:
public sealed class ValuePusher : IDisposable
{
private readonly ValueReceiver _receiver;
private readonly IScheduler _scheduler;
private readonly Subject<int> _subject;
private int _value;
public ValuePusher(ValueReceiver receiver, IScheduler scheduler)
{
_receiver = receiver;
_scheduler = scheduler;
// Arrange to push values to `receiver` dependency
_subject = new Subject<int>();
_subject.ObserveOn(_scheduler)
//.Sample(TimeSpan.FromMilliseconds(50), _scheduler)
.SubscribeOn(_scheduler)
.Subscribe(i => PushCurrentValueToReceiver());
}
public int Value
{
get => _value;
set
{
_value = value;
_subject.OnNext(0);
}
}
private void PushCurrentValueToReceiver()
{
_receiver.Value = Value;
}
public void Dispose()
{
_subject?.OnCompleted();
_subject?.Dispose();
}
}
public class ValueReceiver
{
public int Value { get; set; }
}
I write a unit test for the code above, involving a Microsoft.Reactive.Testing.TestScheduler, which passes:
[TestMethod]
[Timeout(1000)]
public void ReceiverReceivesValueFromPusherViaScheduler()
{
var scheduler = new TestScheduler();
var receiver = new ValueReceiver();
using (var pusher = new ValuePusher(receiver, scheduler))
{
scheduler.Start();
pusher.Value = 1;
scheduler.AdvanceBy(1);
Assert.AreEqual(1, receiver.Value);
}
}
However, if uncomment the call to Sample method the test fails to complete and times-out. How can I change the test code or the production code to verify that values are pushed to the receiving object when Sample is in use?
Source code: https://github.com/DanStevens/StackOverflow71409012
The reason why it times out, seems to be the combination of .Sample(...) and scheduler.Start().
scheduler.Start() tries execute everything that has been scheduled, but I think Sample() keeps scheduling a sample, and thus scheduler.Start() never finishes.
So if you remove scheduler.Start(), and do this instead:
...
// Following line instead of scheduler.Start(), needed because of the .SubscribeOn(...) call
scheduler.AdvanceBy(1);
pusher.Value = 1;
scheduler.AdvanceBy(TimeSpan.FromMilliseconds(50).Ticks);
Assert.AreEqual(1, receiver.Value);
...
it should work with or without the call to .Sample(...).
[Edit] as per Dan Stevens' comment.

Can I keep an unserialisable object between requests?

I have created an .NET Core API project. It works but it creates a new object for each get request. Where can I save the object so that I can reuse it? I have searched Google and found Session but that only seems to store bytes or serialised bytes. I don't think I can serialise the object.
If doSomeInitialisation() takes 1 seconds, creating a new SomeLibrary at each get request when the arg1 is the same does not seem efficient and SomeLibrary is not serialisable so it cannot be stored to the Session.
[HttpGet("{arg1}/{arg2}")]
public IActionResult Get(string arg1, string arg2)
{
var someLibrary = new SomeLibrary();
someLibrary.doSomeInitialisation(arg1);
return someLibrary.doSomething(arg2);
}
Requests
httpx://..../dog/1
httpx://..../dog/2
httpx://..../dog/3
httpx://..../cat/1
httpx://..../cat/2
I could reuse the same SomeLibrary object for the first three requests.
I suppose you use DI in your project. First of all read this article Dependency injection in ASP.NET Core. Then you'll realize that you can use following code to register only one instance per application:
//Startup.cs
services.AddSingleton<ISomeLibrary>(new SomeLibrary());
....
//controller
public SomeController : Controller
{
private readonly ISomeLibrary _sl;
public SomeController(ISomeLibrary sl)
{
_sl = sl;
}
...
}
UPDATE:
According to your last comment you can implement it like this:
public interface ISmthResolver
{
ISomeLibrary Get(string arg);
}
...
public class SmthResolver : ISmthResolver
{
private readonly ConcurrentDictionary<string, Lazy<ISomeLibrary>> _instances = new ConcurrentDictionary<string, Lazy<ISomeLibrary>>();
public ISomeLibrary Get(string arg) => _instances.GetOrAdd(arg, key => new Lazy<ISomeLibrary>(() => new SomeLibrary())).Value;
}
...
services.AddSingleton<SmthResolver, ISmthResolver>();
...
public class Some
{
public Some(ISmthResolver sr)
{
var sl = sr.Get("arg");
}
}
Also read this Making ConcurrentDictionary GetOrAdd thread safe using Lazy.
You can try on singleton pattern,but you should be considering that if it fits your demands because singleton pattern is not a good way for all classes.
public class Singleton
{
private static string _locker = new object();
private static Singleton _instance = null;
public string SerializedString="";
///Constructore is called just one time !
public Singleton(arg1){
DoSerialization(arg1);
}
public static Singleton Instance
{
get
{
if (_instance == null)
{
lock (_locker)
{
if (_instance == null)
{
_instance = new Singleton();
}
}
}
return _instance;
}
}
private void DoSerialization(arg1){
this.SerializedString=JsonConvert.SerializeObject(arg1)
}
}
and use it like this
var SameInstance=new Singleton(arg1).Instance;
var serialized=SameInstance.SerializedString;

ReactiveExtension that was working on old computer is now failing

I'm using the code from Weak Events in .Net, the easy way to handle monitoring changes to an observable collection. The code has worked without any problems for months. I recently updated to a new computer. After getting everything setup and pulling down the code from my repository I encountered a strange problem. The code no longer works!
Here's the relevant portion of my code, it all takes place in the constructor:
public class PurchaseOrderReceipt : BaseEntity
{
/// <summary>
/// Initializes a new instance of the <see cref="PurchaseOrderReceipt" /> class.
/// </summary>
public PurchaseOrderReceipt()
{
this.ReceiptItems = new ObservableCollection<PurchaseOrderItemReceipt>();
this.DateReceived = DateTime.Now;
this.ReceiptItems.ObserveCollectionChanged()
.SubscribeWeakly(this, (target, eventArgs) => target.ReceiptItemsChanged());
}
The exception is thrown on the SubscribeWeakly line with the following error message: ArgumentException: onNext must refer to a static method, or else the subscription will still hold a strong reference to target
I can recreate the problem in LinqPad just by creating an instance of the PurchaseOrderReceipt.
Odder still if I write a simple class in LinqPad that mirrors the setup in the PurchaseOrderReceipt class than it works.
LinqPad code:
void Main()
{
var x = new Test();
x.ReceiptItems.Add(new PurchaseOrderItemReceipt());
}
public class Test:BaseEntity
{
public ObservableCollection<PurchaseOrderItemReceipt> ReceiptItems {get; set;}
public Test()
{
this.ReceiptItems = new ObservableCollection<PurchaseOrderItemReceipt>();
this.ReceiptItems.ObserveCollectionChanged().SubscribeWeakly(this,(target, eventargs) => target.TestChanged());
}
private void TestChanged()
{
"Changed!".Dump();
}
}
Changed! is printed out in the results window.
Here's the CustomReactiveExtension class from the link at the top.
public static class CustomReactiveExtension
{
public static IObservable<EventPattern<NotifyCollectionChangedEventArgs>> ObserveCollectionChanged(this INotifyCollectionChanged collection)
{
return Observable.FromEventPattern<NotifyCollectionChangedEventHandler, NotifyCollectionChangedEventArgs>(
handler => (sender, e) => handler(sender, e),
handler => collection.CollectionChanged += handler,
handler => collection.CollectionChanged -= handler);
}
public static IDisposable SubscribeWeakly<T, TTarget>(this IObservable<T> observable, TTarget target, Action<TTarget, T> onNext) where TTarget : class
{
var reference = new WeakReference(target);
if (onNext.Target != null)
{
throw new ArgumentException("onNext must refer to a static method, or else the subscription will still hold a strong reference to target");
}
IDisposable subscription = null;
subscription = observable.Subscribe(item =>
{
var currentTarget = reference.Target as TTarget;
if (currentTarget != null)
{
onNext(currentTarget, item);
}
else
{
subscription.Dispose();
}
});
return subscription;
}
}
Any ideas?
I am not 100% certain but my guess is that either different versions of the compiler or different compilation options are resulting in your lambda being compiled to an instance method rather than a static method.
The easiest solution to this would be to explicitly implement a static method to be used as your onNext callback, i.e:
private static void OnReceiptItemsChanged(PurchaseOrderReceipt target,
EventPattern<NotifyCollectionChangedEventArgs> eventPattern)
{
// TODO Do something here
}
And then use SubscribeWeakly like so:
this.ReceiptItems.ObserveCollectionChanged().SubscribeWeakly(this, OnReceiptItemsChanged);
Now regardless of which compiler you use or which compilation options the callback is always a static method.

Weak References stays alive

I have an interface: IRemoteDataChangedListener
public interface IRemoteDataChangedListener<TData>
{
void DataReceived(TData newData);
}
And a class, RealtimeEventService
public class RealtimeEventService : IRealtimeEventService
{
private readonly IEventListener listener;
private readonly List<Tuple<Type, WeakReference>> dataCreated;
public RealtimeEventService(IEventListener eventListener)
{
this.dataCreated = new List<Tuple<Type, WeakReference>>();
this.listener = eventListener;
this.listener.EventReceived += this.ListenerOnEventReceived;
}
private void ListenerOnEventReceived(EventMessage message)
{
Type type = message.GetType();
if (type == typeof(NotificationReadEventMessage))
{
this.DataChanged((NotificationReadEventMessage)message);
}
}
public void SubscribeDataChanged<TEventMessage>(IRemoteDataChangedListener<TEventMessage> dataChangedListener) where TEventMessage : EventMessage, new()
{
this.dataCreated.Add(Tuple.Create(typeof(TEventMessage), new WeakReference(dataChangedListener)));
}
internal void DataChanged<TKey>(TKey newData)
where TKey : class, new()
{
LoopAndFilter<TKey>(this.dataCreated, listener => listener.DataReceived(newData));
}
private static void LoopAndFilter<TKey>(ICollection<Tuple<Type, WeakReference>> collection,
Action<IRemoteDataChangedListener<TKey>> success) where TKey : class
{
foreach (var reference in collection.ToArray())
{
if (!reference.Item2.IsAlive)
{
collection.Remove(reference);
continue;
}
if (reference.Item1 != typeof(TKey))
continue;
success((IRemoteDataChangedListener<TKey>)reference.Item2.Target);
}
}
#endregion
}
Whenever I create a test class that inherits IRemoteDataChangedListener with NotificationReadEventMessage as generic argument, and use an instance of this class with SubscribeDataChanged(), it gets hooked up just fine, and the method gets called.
Problem is, when I set the instance reference to null and run GC.Collect(), it should then be null, and the next time RealtimeEventService's LoopAndFilter method runs, it should detect that it is no longer alive, and remove the Weakreference from the list.
However it does not. When I inspect the value (In LoopAndFilter), after setting the instance reference to null in the test, the value still shows up as Alive being true.
And now I've been staring at this code for hours, and I simply cannot find anywhere I'd have a strong reference to the class...
Any help?
#Edit: Unit test (Using the Moq and Should libraries):
public class RealtimeEventServiceTests
{
[Fact]
public void VerifyWeakReferencesWorksAsIntended()
{
var eventListenerMock = new Mock<IEventListener>();
IRealtimeEventService service = new RealtimeEventService(eventListenerMock.Object);
bool called = false;
RemoteDataTest dataChangedListener = new RemoteDataTest();
dataChangedListener.Called += (sender, args) => called = true;
service.SubscribeDataChanged(dataChangedListener);
called.ShouldBeFalse();
((RealtimeEventService)service).DataChanged(new NotificationReadEventMessage());
called.ShouldBeTrue();
called = false;
dataChangedListener = null;
GC.Collect();
called.ShouldBeFalse();
((RealtimeEventService)service).DataChanged(new NotificationReadEventMessage());
called.ShouldBeFalse();
}
}
public class RemoteDataTest : IRemoteDataChangedListener<NotificationReadEventMessage>
{
public event EventHandler Called;
public void DataReceived(NotificationReadEventMessage newData)
{
if (Called != null) Called(this, null);
}
}
As it turns out, when I got home and compiled it at home, it ran just fine. And when I got back to work, it worked fine there as well.
Guess it's just one of those spooky bugs that magically vanish at inexplicable times. I'm just glad to be rid of it.
I did take the advice of Ewan & Scott Chamberlain, so thanks for that!

In a C# 'using' block, how best to access the IDisposable in contained extension method calls?

I am writing extension methods for a class, and would like to access an IDisposable object defined in a using block which will often contain calls to the extension methods.
I do not want to simply pass the IDisposable to the method calls, which would detract from the simplicity of my API's programming model. Accomplishing what I'm after would also make the code work much more like the third-party API with which I'm integrating.
I can imagine one way to go about this: register the IDisposable in some global location, perhaps tied to the current thread ID so it can be looked up in the extension methods via a factory method call or some such thing. The object could unregister itself when the using block is exited and its Dispose() method is eventually called (to make this work I imagine I might need to use a weak reference, though).
That doesn't seem very unclean, but it is a little too much roundabout for my taste. Is there some more direct way of doing this?
Here's what I'd like to do:
public static class ExtensionMethods {
public static void Foo(this Bar b) {
// Access t to enable this extension method to do its work, whatever that may be
}
}
public class Bar {
}
public class Schlemazel {
public void DoSomething() {
using (Thingamabob t = new Thingamabob()) {
Bar b = new Bar();
b.Foo();
}
}
}
EDIT:
Following is a solution implemented using weak references and a simple thread-based registration system. It seems to work and to be stable even under a fair load, but of course on a really overloaded system it could theoretically start throwing errors due to lock contention.
I thought it might be interesting for someone to see this solution, but again, it introduces needless complexity and I am only willing to do this if necessary. Again, the goal is a clean extension of a third-party API, where I can call extension methods on objects created by the third-party API, where the extension methods depend on some context that is messy to create or get for each little extension method call.
I've left in some console output statements so that if you're curious, you can actually plop these classes into a command-line project and see it all in action.
public class Context : IDisposable
{
private const int MAX_LOCK_TRIES = 3;
private static TimeSpan MAX_WRITE_LOCK_TIMEOUT = TimeSpan.FromTicks(500);
private static System.Threading.ReaderWriterLockSlim readerWriterLock = new System.Threading.ReaderWriterLockSlim();
static IDictionary<string, WeakReference<Context>> threadContexts = new Dictionary<string, WeakReference<Context>>();
private bool registered;
private string threadID;
private string ThreadID
{
get { return threadID; }
set
{
if (threadID != null)
throw new InvalidOperationException("Cannot associate this context with more than one thread");
threadID = value;
}
}
/// <summary>
/// Constructs a Context suitable for use in a using() statement
/// </summary>
/// <returns>A Context which will automatically deregister itself when it goes out of scope, i.e. at the end of a using block</returns>
public static Context CreateContext()
{
Console.WriteLine("CreateContext()");
return new Context(true);
}
private Context(bool register)
{
if (register)
{
registered = true;
try
{
RegisterContext(this);
}
catch
{
registered = false;
}
}
else
registered = false;
}
public Context()
{
registered = false;
}
public void Process(ThirdPartyObject o, params string[] arguments)
{
Console.WriteLine("Context.Process(o)");
// Process o, sometimes using the third-party API which this object has access to
// This hides away the complexity of accessing that API, including obviating the need
// to reconstruct and configure heavyweight objects to access it; calling code can
// blithely call useful methods on individual objects without knowing the messy details
}
public void Dispose()
{
if (registered)
DeregisterContext(this);
}
private static void RegisterContext(Context c)
{
if (c == null)
throw new ArgumentNullException();
c.ThreadID = System.Threading.Thread.CurrentThread.ManagedThreadId.ToString();
Console.WriteLine("RegisterContext() " + c.ThreadID);
bool lockEntered = false;
int tryCount = 0;
try
{
while (!readerWriterLock.TryEnterWriteLock(TimeSpan.FromTicks(5000)))
if (++tryCount > MAX_LOCK_TRIES)
throw new OperationCanceledException("Cannot register context (timeout)");
lockEntered = true;
threadContexts[c.ThreadID] = new WeakReference<Context>(c);
}
finally
{
if (lockEntered)
readerWriterLock.ExitWriteLock();
}
}
private static void DeregisterContext(Context c)
{
if (c == null)
throw new ArgumentNullException();
else if (!c.registered)
return;
Console.WriteLine("DeregisterContext() " + c.ThreadID);
bool lockEntered = false;
int tryCount = 0;
try
{
while (!readerWriterLock.TryEnterWriteLock(TimeSpan.FromTicks(5000)))
if (++tryCount > MAX_LOCK_TRIES)
throw new OperationCanceledException("Cannot deregister context (timeout)");
lockEntered = true;
if (threadContexts.ContainsKey(c.ThreadID))
{
Context registeredContext = null;
if (threadContexts[c.ThreadID].TryGetTarget(out registeredContext))
{
if (registeredContext == c)
{
threadContexts.Remove(c.ThreadID);
}
}
else
threadContexts.Remove(c.ThreadID);
}
}
finally
{
if (lockEntered)
readerWriterLock.ExitWriteLock();
}
}
/// <summary>
/// Gets the Context for this thread, if one has been registered
/// </summary>
/// <returns>The Context for this thread, which would generally be defined in a using block using Context.CreateContext()</returns>
internal static Context GetThreadContext()
{
string threadID = System.Threading.Thread.CurrentThread.ManagedThreadId.ToString();
Console.WriteLine("GetThreadContext() " + threadID);
bool lockEntered = false;
int tryCount = 0;
try
{
while (!readerWriterLock.TryEnterReadLock(TimeSpan.FromTicks(5000)))
if (++tryCount > MAX_LOCK_TRIES)
throw new OperationCanceledException("Cannot get context (timeout)");
lockEntered = true;
Context registeredContext = null;
if (threadContexts.ContainsKey(threadID))
threadContexts[threadID].TryGetTarget(out registeredContext);
return registeredContext;
}
finally
{
if (lockEntered)
readerWriterLock.ExitReadLock();
}
}
}
// Imagine this is some third-party API
public static class ThirdPartyApi
{
// Imagine this is any call to the third-party API that returns an object from that API which we'd like to decorate with an extension method
public static ThirdPartyObject GetThirdPartyObject()
{
return new ThirdPartyObject();
}
}
// Imagine this is some class from a third-party API, to which we would like to add extension methods
public class ThirdPartyObject
{
internal ThirdPartyObject() { }
}
public static class ExtensionMethods
{
public static void DoSomething(this ThirdPartyObject o) {
// get the object I need to access resources to do my work
Console.WriteLine("o.DoSomething()");
Context c = Context.GetThreadContext();
c.Process(o);
}
}
You could test it pretty simply, with some code like this:
ThirdPartyObject o;
using (Context.CreateContext())
{
o = ThirdPartyApi.GetThirdPartyObject(); // or a call to my own code to get it, encapsulating calls to the third-party API
// Call the method we've tacked on to the third party API item
o.DoSomething();
}
try
{
// If the registered context has been disposed/deregistered, this will throw an error;
// there is of course no way of knowing when it will happen, but in my simple testing
// even this first attempt always throws an error, on my relatively unburdened system.
// This means that with this model, one should not access the using-block Context
// outside of the using block, but that's of course true in general of using statements
o.DoSomething();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
System.Threading.Thread.Sleep(1000);
try
{
// Should almost certainly see an error now
o.DoSomething();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
Pass the t variable to the extension method.
public static class ExtensionMethods {
public static void Foo(this Bar b, Thingamabob t) {
// Access t to enable this extension method to do its work, whatever that may be
}
}
public class Bar { }
public class Schlemazel {
public void DoSomething() {
using (Thingamabob t = new Thingamabob()) {
Bar b = new Bar();
b.Foo(t);
}
}
}

Categories