How to dispose resources in third-party dll? - c#

I have a console application that needs to create multiple objects of type <T> and T is inside another dll that I don’t own.
When an object of type T is created, it loads a XML in memory, but it never releases it.
So if you create too many objects of type T, an OutOfMemoryException is thrown.
The dll doesn't provide a dispose method for that Object and I can’t interact with the XML directly.
Is there a way to dispose of objects of a certain type that were created by a dll that I don’t own ?
I'm using .NET 4.6
The third-party dll is the dll of Trados Studio, for the people who know the program.

Just set the instance of the 3rd part object to null and create a new instance. The garbage collector will eventually clean up the object that you set to null and you wont get an out of memory exception anymore.
public class Class1
{
private StringBuilder sb = new StringBuilder();
public void loadFile()
{
using(StreamReader sr = new StreamReader("C:\\test.txt")) // Loads large text file.
{
sb.Append(sr.ReadToEnd());
}
}
}
static void Main()
{
fileloader.Class1 inst = new fileloader.Class1(); // Assume this is the instance of your 3rd party object.
do
{
if(inst == null)
{
inst = new fileloader.Class1();
}
for (int i = 0; i < 100; i++)
{
inst.loadFile();
}
inst = null; // allows the object to be GC'ed. Without this i get the OutOfMemoryException
Thread.Sleep(1000);
} while (true);
}

Calling GC.Collect() during runtime might solve the problem.
Ref: https://learn.microsoft.com/en-us/dotnet/api/system.gc.collect?view=net-5.0

Related

Copy an object in universal Windows Application (c#)

In want to add a copy of an object to a List in a universal Windows Application. I tried several ways and found IClonable,BinaryFormatter,IFormatter which are all not available in WinRT applications. Please advice me a suitable way to copy a object to a new object. Find my code below.
foreach (var ctrls in _listctrldata)
{
for (int index = 0; index < ctrls.Controls.Control.Count; )
{
listofcontrolvalues.Add(ctrls.Controls.Control[index]);
index++;
}
SetControlvalues(null, _vcontainer, listofcontrolvalues);
//_vcontainer changes everytime the loop rotates and Should create a copy of _vcontainer here//
VerticalContainer vcont = new VerticalContainer ();
vcont = _vcontainer;
_listcontrols.Add(vcont);
}
I don’t know what the class VerticalContainer is.
If it is a .NET class defined by you self, you can just defined a clone method to create a new object and copy all of the build-in data type fields.
If it is a Windows Runtime class, I’m afraid you cannot easily copy it because there are some internal and private data members you cannot access.
In your code.
VerticalContainer vcont = new VerticalContainer (); vcont = _vcontainer;
You only changed the vcont reference from new created object to the old _vcontainer, this will not work, you need to copy all of fields from _vcontainer to vcont one by one.

Is it possible to execute C# code represented as string?

On my form I have a button click
private void button1_Click(object sender, EventArgs e)
{
do something
}
How on the click would I load my do something from a text file, for example my text file looks like this:
MessageBox.Show("hello");
label1.Text = "Hello";
on click it does everything in my text file, if possible.
Here is a very simple example, just to prove this is possible. Basically, you use CodeDomProvider to compile source at runtime, then execute using reflection.
var provider = CodeDomProvider.CreateProvider("C#");
string src=#"
namespace x
{
using System;
public class y
{
public void z()
{
Console.WriteLine(""hello world"");
}
}
}
";
var result = provider.CompileAssemblyFromSource(new CompilerParameters(), src);
if (result.Errors.Count == 0)
{
var type = result.CompiledAssembly.GetType("x.y");
var instance = Activator.CreateInstance(type);
type.GetMethod("z").Invoke(instance, null);
}
Edit
As #Agat points out, the OP seems to require a sort of scripting framework (it makes use of label1, a property of the current object), whereas my answer above obviously does not provide that. The best I can think of is a limited solution, which would be to require dependencies to be specified explicitly as parameters in the "script". Eg, write the scripted code like this:
string src = #"
namespace x
{
using System.Windows;
public class y
{
public void z(Label label1)
{
MessageBox.Show(""hello"");
label1.Text = ""Hello"";
}
}
}
";
Now you can have the caller examine the parameters, and pass them in from the current context, again using reflection:
var result = provider.CompileAssemblyFromSource(new CompilerParameters(), src);
if (result.Errors.Count == 0)
{
var type = result.CompiledAssembly.GetType("x.y");
var instance = Activator.CreateInstance(type);
var method = type.GetMethod("z");
var args = new List<object>();
// assume any parameters are properties/fields of the current object
foreach (var p in method.GetParameters())
{
var prop = this.GetType().GetProperty(p.Name);
var field = this.GetType().GetField(p.Name);
if (prop != null)
args.Add(prop.GetValue(this, null));
else if (field != null);
args.Add(field.GetValue(this));
else
throw new InvalidOperationException("Parameter " + p.Name + " is not found");
}
method.Invoke(instance, args.ToArray());
}
Like the other answers have stated, it isn't an easy thing to implement and can possibly be done through reflection depending on how advanced your scripts are.
But no one #BrankoDimitrijevic mentioned Roslyn and it is a great tool. http://msdn.microsoft.com/en-us/vstudio/roslyn.aspx
It hasn't been updated in quite awhile (Sept.2012) and doesn't have all of the features of C# implemented, however, it did have a lot of it implemented when I played around with this release.
By adding your assembly as a reference to the scripting session, you're able to gain access to all of your assembly's types and script against them. It also supports return values so you can return any data that a scripted method generates.
You can find what isn't implemented here.
Below is a quick and dirty example of Roslyn that I just wrote and tested. Should work right out of box after installing Roslyn from NuGet. The small bloat at the initialization of the script engine can easily be wrapped up in a helper class or method.
The key is passing in a HostObject. It can be anything. Once you do, your script will have full access to the properties. Notice that you just call the properties and not the host object in the script.
Basically, your host object will contain properties of the data you need for your script. Don't necessarily think of your host object as just a single data object, but rather a configuration.
public class MyHostObject
{
public string Value1 { get; set; }
public string Value2 { get; set; }
}
public class RoslynTest
{
public void Test()
{
var myHostObject = new MyHostObject
{
Value1 = "Testing Value 1",
Value2 = "This is Value 2"
};
var engine = new ScriptEngine();
var session = engine.CreateSession(myHostObject);
session.AddReference(myHostObject.GetType().Assembly.Location);
session.AddReference("System");
session.AddReference("System.Core");
session.ImportNamespace("System");
// "Execute" our method so we can call it.
session.Execute("public string UpdateHostObject() { Value1 = \"V1\"; Value2 = \"V2\"; return Value1 + Value2;}");
var s = session.Execute<string>("UpdateHostObject()");
//s will return "V1V2" and your instance of myHostObject was also changed.
}
}
No. You can not.
At least in any simple way.
The thing you want is something like eval('do something') from javascript.
That's not possible to do with C#. C# is a language which needs compilation before execution unlike javascript (for instance).
The only way to implement that is to build your own (pretty complicated as for beginner) parser and execute it in such way.
UPDATED:
Actually, as JDB fairly noticed, that's really not the only way. I love programming! There are so many ways to make a freakky (or even sometimes that really can be necessary for some custom interesting tasks (or even learning)!) code. he he
Another approach I've got in my mind is building some .cs file, then compiling it on-the-fly and working with it as some assembly or some other module. Right.

Using statement on object passed via parameter

Seeking best inputs on correct usage of C# using statement. Can I use using statement on a parameter object as in the following uncommon example code snippet (viz., multi-layer application)?
Although the code snippet is different from what I feel that the using statement should be in ProcessFileAndReturnNumberFromStream() method of 'Business' class.
Why is it an uncommon practice to use using statement on object passed via parameter? Please correct or elaborate on the flaw?
using System;
using System.IO;
class Data
{
public double? GetNumberFromStream(StreamReader sr)
{
double? number;
try
{
using (sr)
{
number = Convert.ToDouble(sr.ReadToEnd());
return number;
}
}
finally
{
number = null;
}
}
}
class Business
{
public double? ProcessFileAndReturnNumberFromStream()
{
string fileName = "Test.txt";
StreamReader sr = new StreamReader(fileName);
Data dat = new Data();
return dat.GetNumberFromStream(sr);
}
}
class GUI
{
static void Main()
{
Business bus = new Business();
double? number = bus.ProcessFileAndReturnNumberFromStream();
Console.WriteLine(number);
Console.ReadKey();
}
}
Please help.
Thanks
If a method is passed an object that implements IDisposable, it's usually the responsibility of the caller to manage the lifetime of that object, rather than the callee.
public double? ProcessFileAndReturnNumberFromStream()
{
string fileName = "Test.txt";
Data dat = new Data();
using (StreamReader sr = new StreamReader(fileName))
{
return dat.GetNumberFromStream(sr);
}
}
The caller that is passing the instance of IDisposable should be the one to use the using statement. If the callee uses it, the object will be disposed while outside the immediate control of the caller who 'owns' the object.
Can I use using statement on a parameter object as in the following uncommon example code snippet (viz., multi-layer application)?
You can, but it's generally odd to do so. Usually whatever is creating the StreamReader would be expecting to "own" it and dispose of it when they're done with it. It would be more usual for your ProcessFileAndReturnNumberFromStream method to be:
using (StreamReader sr = new StreamReader(fileName))
{
Data dat = new Data();
return dat.GetNumberFromStream(sr);
}
(Although I'd personally use File.OpenText instead of explicitly constructing the StreamReader.)
Your GetNumberFromStream method would then not need the using statement. It also doesn't need the try/finally block at all - it's an odd implementation all round, given that it will never return null, either...
It's also odd that you're creating a new instance of Data and then doing nothing with it - as your GetNumberFromStream method doesn't use an instance variables or override a base class method, you should consider making it static.
Such API would be extremely troublesome.
You would never know whether or not the object passed to a method is disposed inside the method or not. Thus, if this is you who create the object and pass it there, you would also never know whether or not you should dispose the object you have just created and passed to the method or not.
I guess then, while this is technically possible, it would promote the bad programming style.

Is it possible to load two different ole com libraries with the same GUID/CLSID at the same time in C#

I have three vendor supplied ole com libraries that provide an interface to different but similar devices. These libraries are not compatible between devices, and have differing functions embedded. They also all share the same ID's, so I can only register one on a machine at a time. Unfortunately I do not have the source and have no way of recompiling these.
My problem is that quite often I need to be able to communicate with more than one model of device.
I've tried loading the dll from a specific path and converting it to an assembly, creating an instance of it and pulling out the methodinfo for the functions I need. This appears to work. The type information is different for the different libraries as expected, but whenever I instantiate it it still appears to only load the registered dll, since it crashes and burns with an access violation if I call a function that is not in the currently registered dll. Does anyone have any ideas?
[DllImport("oleaut32.dll", CharSet = CharSet.Unicode, PreserveSig = false)]
public static extern void LoadTypeLibEx(String strTypeLibName, RegKind regKind, [MarshalAs(UnmanagedType.Interface)] out Object typeLib);
public enum RegKind
{
RegKind_Default = 0,
RegKind_Register = 1,
RegKind_None = 2
}
private void Initialize() {
Type ct;
object typeLib;
try {
// Load DLL
LoadTypeLibEx(#"c:\temp\zkA11C\zkemkeeper.dll", RegKind.RegKind_None, out typeLib);
if (typeLib == null)
throw new Exception("LoadTypeLibEx returned null pointer");
TypeLibConverter converter = new TypeLibConverter();
ConversionEventHandler eventHandler = new ConversionEventHandler();
AssemblyBuilder zkA11C = converter.ConvertTypeLibToAssembly(typeLib, "zkA11C.dll", 0, eventHandler, null, null, null, null);
// Get class type
ct = zkA11C.GetType("zkA11C.CZKEMClass");
// Create instance of the class
dllClassInstance = Activator.CreateInstance(ct);
// Get method info for functions
fmiConnect = ct.GetMethod("Connect_Net");
...
}
catch (Exception e) {
throw new Exception("Failed to load library: " + e.Message);
}
}

"using" keyword in java [duplicate]

Does Java have a using statement that can be used when opening a session in hibernate?
In C# it is something like:
using (var session = new Session())
{
}
So the object goes out of scope and closes automatically.
Java 7 introduced Automatic Resource Block Management which brings this feature to the Java platform. Prior versions of Java didn't have anything resembling using.
As an example, you can use any variable implementing java.lang.AutoCloseable in the following way:
try(ClassImplementingAutoCloseable obj = new ClassImplementingAutoCloseable())
{
...
}
Java's java.io.Closeable interface, implemented by streams, automagically extends AutoCloseable, so you can already use streams in a try block the same way you would use them in a C# using block. This is equivalent to C#'s using.
As of version 5.0, Hibernate Sessions implement AutoCloseable and can be auto-closed in ARM blocks. In previous versions of Hibernate Session did not implement AutoCloseable. So you'll need to be on Hibernate >= 5.0 in order to use this feature.
Before Java 7, there was no such feature in Java (for Java 7 and up see Asaph's answer regarding ARM).
You needed to do it manually and it was a pain:
AwesomeClass hooray = null;
try {
hooray = new AwesomeClass();
// Great code
} finally {
if (hooray!=null) {
hooray.close();
}
}
And that's just the code when neither // Great code nor hooray.close() can throw any exceptions.
If you really only want to limit the scope of a variable, then a simple code block does the job:
{
AwesomeClass hooray = new AwesomeClass();
// Great code
}
But that's probably not what you meant.
Since Java 7 it does: http://blogs.oracle.com/darcy/entry/project_coin_updated_arm_spec
The syntax for the code in the question would be:
try (Session session = new Session())
{
// do stuff
}
Note that Session needs to implement AutoClosable or one of its (many) sub-interfaces.
Technically:
DisposableObject d = null;
try {
d = new DisposableObject();
}
finally {
if (d != null) {
d.Dispose();
}
}
The closest java equivalent is
AwesomeClass hooray = new AwesomeClass();
try{
// Great code
} finally {
hooray.dispose(); // or .close(), etc.
}
As of now, no.
However there is a proposal of ARM for Java 7.
If you're interested in resource management, Project Lombok offers the #Cleanup annotation. Taken directly from their site:
You can use #Cleanup to ensure a given
resource is automatically cleaned up
before the code execution path exits
your current scope. You do this by
annotating any local variable
declaration with the #Cleanup
annotation like so:
#Cleanup InputStream in = new FileInputStream("some/file");
As a
result, at the end of the scope you're
in, in.close() is called. This call is
guaranteed to run by way of a
try/finally construct. Look at the
example below to see how this works.
If the type of object you'd like to
cleanup does not have a close()
method, but some other no-argument
method, you can specify the name of
this method like so:
#Cleanup("dispose") org.eclipse.swt.widgets.CoolBar bar = new CoolBar(parent, 0);
By default, the cleanup method is presumed to be
close(). A cleanup method that takes
argument cannot be called via
#Cleanup.
Vanilla Java
import java.io.*;
public class CleanupExample {
public static void main(String[] args) throws IOException {
InputStream in = new FileInputStream(args[0]);
try {
OutputStream out = new FileOutputStream(args[1]);
try {
byte[] b = new byte[10000];
while (true) {
int r = in.read(b);
if (r == -1) break;
out.write(b, 0, r);
}
} finally {
out.close();
}
} finally {
in.close();
}
}
}
With Lombok
import lombok.Cleanup;
import java.io.*;
public class CleanupExample {
public static void main(String[] args) throws IOException {
#Cleanup InputStream in = new FileInputStream(args[0]);
#Cleanup OutputStream out = new FileOutputStream(args[1]);
byte[] b = new byte[10000];
while (true) {
int r = in.read(b);
if (r == -1) break;
out.write(b, 0, r);
}
}
}
No, Java has no using statement equivalent.
In java 8 you can use try. Please refer to following page. http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
Please see this List of Java Keywords.
The using keyword is unfortunately not part of the list.
And there is also no equivalence of the C# using keyword through any other keyword as for now in Java.
To imitate such "using" behaviour, you will have to use a try...catch...finally block, where you would dispose of the resources within finally.
ARM blocks, from project coin will be in Java 7. This is feature is intended to bring similar functionality to Java as the .Net using syntax.
To answer the question regarding limiting scope of a variable, instead of talking about automatically closing/disposing variables.
In Java you can define closed, anonymous scopes using curly brackets. It's extremely simple.
{
AwesomeClass hooray = new AwesomeClass()
// Great code
}
The variable hooray is only available in this scope, and not outside it.
This can be useful if you have repeating variables which are only temporary.
For example, each with index. Just like the item variable is closed over the for loop (i.e., is only available inside it), the index variable is closed over the anonymous scope.
// first loop
{
Integer index = -1;
for (Object item : things) {index += 1;
// ... item, index
}
}
// second loop
{
Integer index = -1;
for (Object item : stuff) {index += 1;
// ... item, index
}
}
I also use this sometimes if you don't have a for loop to provide variable scope, but you want to use generic variable names.
{
User user = new User();
user.setId(0);
user.setName("Andy Green");
user.setEmail("andygreen#gmail.com");
users.add(user);
}
{
User user = new User();
user.setId(1);
user.setName("Rachel Blue");
user.setEmail("rachelblue#gmail.com");
users.add(user);
}

Categories

Resources