VB NET How to execute some code at the start and at the end of any function - vb.net

I like to try to optimize my code, and I would like to measure the time taken by a function.
I have a class named Chrono. So I just have to add chrono.start at the beginning of the function, and chrono.stop at the end. My class chan also add the times it measure in a list, to then have average time, total time...
It works. Only problem is when there is exit sub or return in the middle of the function. Not really a problem, I just add a Try at the begginf of the function, and put my chrono.stop in the finally portion. I'm not sure it's really efficient, but it works.
So here is my question : I would like to have a function taking function name as parameter, that will automatically launch and stop my class when this function is called. I have heard of Reflection, but I have no idea how to use it. And it's really hard to search for this question in the internet (because the words are too common : "do something at the end of a function")
To resume, my code works, no problem. It's just constraining to add code to a function for just a short period of time (and sometimes forgot to remove it).
Thx (I'm french and hope I'm understandable)

This is how you can use reflection to call a method by name:
using System.Reflection;
public int InvokeMethod(string name)
{
int time1 = 1; //call your chrono.start here.
Type thisType = this.GetType();
MethodInfo theMethod = thisType.GetMethod(name);
theMethod.Invoke(this, new object[] { 1 });
int time2 = 10; //call your chrono.end here.
return time2 - time1;
}
However, there is a problem. How will you know what parameters to pass to the function? In the code above, I'm passing the integer 1 (new object[] { 1 }) just for example. So this code cannot be automated, but if you run it manually against each function one by one, then you can change that line to pass the correct arguments and make it work without having to modify your function.
This is to answer your question as how to call a function by name using reflection. However, it is much easier to call it using a delegate (or Fuc<T, tRsult> in .Net v3.5 and higher).

Related

Using a function without returning a value visual basic

I'm making a batch development kit in visual basic and i need to be able to call a function that sets textboxes to a saved files text. How do i do this without returning? I tried this, and it lets me run the program, but gives me a warning, not an error. How do i go about doing this? Here is my little function design. P.S. I recently switched back to VB from Java and i'm so used to doing public void. Thanks in advance!
Public Function loadProject()
End Function
You want a Sub, which is the equivalent to the Java void method.
Public Sub LoadProject()
End Sub
It's not a bad Idea to just have a function that returns a value like a success statement just in case you need it. A call to the function doesn't have to accept or use the return value from the function.
You could even build a class with two values - txtpreviousvalue and txtnewvalue
Have your function return that type and fill an instance of the type with the respective values.
One day, if you need it, you'll have it.
P.S. I'm only posting this as an answer because the good answer posted by sstan is not marked as the answer; You should probably do that.

Rx Observable only works once?

I have the following code which is being called from a Web Api. As you can see I want to return as soon as I can and shift the work onto the threadpool. (The client polls to see when the job is complete. But the polling is nothing to do with this. The purpose of these routines is simply to extract data and write a file away in background whilst maintaining the progress of the job in a table. The client will interrogates this to determine whether the file is ready so I'm not trying to push progress messages to the client.)
Public Function Extract(filepath as string, ...) as ExtractResult
dim source = ExtractInternal(filepath, ...)
' works first time it is called only!
using source.SubscribeOn(ThreadPoolScheduler.Instance)
.SubScribe()
end using
' works every time it is called ...
dim subscription = source.SubscribeOn(ThreadPoolScheduler.Instance)
.SubScribe()
Return New ExtractResult()
End Function
Public Function ExtractInternal(filepath as string, ...) as IObservable(of Unit)
return Observable.Create(of Unit)
Function()
....
uses filepath here
Return Disposable.Empty
End Function
End Function
As you can see in my comments, if I use auto-disposing of Using ..., I am finding that the observable gets called on the first occasion but not thereafter. Whereas if I assign the subscription to a local var it works every time the web call invokes the routine but I'm concerned that I'm actually leaving stuff hanging around.
Could someone explain why the observable doesn't get re-instantiated on subsequent calls and perhaps explain how I can get it to work every time and tidy up afterwards properly.
EDIT:
So I ended up using Observable.Defer which seems tom give me what I am after ...
Public Function Extract(filepath as string, ...) As ExtractResult
Observable.Defer(Function() ExtractInternal(filepath, ...) _
.SubscribeOn(NewThreadScheduler.Default) _
.Subscribe()
Return New ExtractResult()
End Function
I'm wondering if this is perhaps the correct way to do it to give me proper disposal whilst also using the current parameter values.
Could anyone confirm or correct?
EDIT 2
That was wrong! In fact if I rewrite it as
Public Function Extract(filepath as string, ...) As ExtractResult
Using Observable.Defer(Function() ExtractInternal(filepath, ...)
.SubscribeOn(NewThreadScheduler.Default) _
.Subscribe()
End Using
Return New ExtractResult()
End Function
I get the same behaviour as I originally was getting when I wrote the post.
One thing (amongst many) I don't understand is why if the observable is local var, when a second call is made to the Extract method, another observable is not created and subscribed to? It seems to go against scoping logic if I am actually referencing the same observable under the hood? I've obviously misunderstood.
Many thx
S
Yes, when you dispose the subscription, it stops receiving notifications.
You should keep it in an instance field and have the class implement disposable. Consumers of this class can then dispose it at their convenience.
In your Dispose implementation, you call subscription.Dispose().

Custom parameters in Pentaho dashboards

Custom parameters in a CDE/CTools dashboard are great for defaulting initial values of parameters, e.g. setting a date parameter to today. i.e. the parameter looks like:
function() {
// some code
return val
}
However there is an issue with them. The first time you access a "custom parameter" in code, it is a function not a string. So you have to use:
paramName()
To get its value.
Once the end user selects a value then you have to use
paramName
This is really awkward in complicated dashboards with lots of prompts. Is there a better way this can be done? (Perhaps there is something in javascript I'm missing to help here?)
OK, there is a solution, but I dont like it!
First; Move all the init code into named procedures e.g.
function monthInit() {
return "june";
}
Then in the custom parameter for month, just say:
monthInit();
That way the custom parameter is always a string, and never starts off as a function.
Not ideal though because then all your init code is in a separate bit of js.

How to make function wait to return after getResult from SQL Statement is available?

I'm just trying to make a simple function that will return all the data from my SQLITE database as an array. But it looks like when my function is returning the array, the SQL statement is actually still executing... so it's empty... Does anyone have a suggestion? Or am I just going about this whole thing wrong.
I know I could just have the event listener functions outside this function, and they could then set the data. But i'm trying to make a AS3 Class that holds all my SQL functions, and It would be nice to have everything for this particular function just in one function, so it can return an array to me.
public function getFavsGamesArray():Array
{
getFavsArraySql.addEventListener(SQLEvent.RESULT, res);
getFavsArraySql.addEventListener(SQLErrorEvent.ERROR, error);
getFavsArraySql.text = "SELECT * FROM favGames";
getFavsArraySql.execute();
var favsArr:Array = new Array();
function res(e:SQLEvent):void
{
trace("sql good!");
favsArr=getFavsArraySql.getResult().data;
}
function error(e:SQLEvent):void
{
trace("sql error!");
}
trace(favsArr);
return favsArr;
}
Assuming I understood your question, Instead of expecting getFavsGamesArray() to actually return the results from an asynchronous event (which it likely never will), consider passing a function (as an argument) to call within your res() function that would then process the data.
In your SQL helper class, we'll call it SQLHelper.as:
private var processResultsFun:Function;
public function getFavsGamesArray(callBackFun:Function):void
{
processResultsFun = callBackFun;
...
} //Do not return array, instead leave it void
function res(e:SQLEvent):void
{
trace("sql good!");
if(processResultsFun != null)
{
processResultsFun(getFavsArraySql.getResult().data);
}
}
In the class(es) that call your SQL helper class:
function processRows(results:Array):void {
//Make sure this function has an Array argument
//By the time this is called you should have some results
}
...
SQLHelper.getFavsGamesArray(processRows);
You can optionally pass an error handling function as well.
Your problem is that your task is asynchronous.
favsArris a temporary variable, and you return its value directly when getFavsGamesArray completes. At that time, the value will always be null, because the listener methods are called only after the SQL statement is complete - which will be at some time in the future.
You need some way to delay everything you are going to do with the return value, until it actually exists.
The best way to do it is to dispatch your own custom event, and add the value as a field to the event object, or to add a listener method outside of your SQL class directly to the SQLStatement - and have it do stuff with event.target.getResult().data. That way you can always be sure the value exists, when processing occurs, and you keep your SQL behavior decoupled from everything on the outside.
I would also strongly encourage you not to declare your event listeners inside functions like this: You can't clean up these listeners after the SQL statements completes!
True: Declaring a function inside a function makes it temporary. That is, it exists only for the scope of your function, and it is garbage collected when it's no longer needed - just like temporary variables. But "it is no longer needed" does not apply if you use it as an event listener! The only reason this works at all is that you don't use weak references - if you did, the functions would be garbage collected before they are even called. Since you don't, the listeners will execute. But then you can't remove them without a reference! They continue to exist, as will the SQL statement, even if you set its references to null - and you've successfully created a memory leak. Not a bad one, probably, but still...
If you really want to encapsulate your SQL behavior, that is a good thing. Just consider moving each SQL statement to a dedicated class, instead of creating one giant SQLHelper, and having your listener methods declared as member functions - it is much easier to prevent memory leaks and side effects, if you keep references to everything, and you can use these in a destroy method to clean up properly.

Why does a VB.Net function that returns string only actually return a single character?

I'm calling a function that returns a string, but it's only actually returning the first character of the string it's supposed to be returning.
Here's a sample piece of code to recreate the issue I'm experiencing:
Public Function GetSomeStringValue(Value as Integer) As String
... Code Goes here
Return Some_Multicharacter_string
End Function
The function call looks like:
SomeStringValue = GetSomeStringValue(Value)
Why is this not returning the entire string?
Note: this answer was originally written by the OP, Kibbee, as a self-answer. However, it was written in the body of the question, not as an actual separate answer. Since the OP has refused repeated requests by other users, including a moderator, to repost in accordance with site rules, I'm reposting it myself.
After trying a hundred different things, refactoring my code, stepping through the code in the debugger many times, and even having a co-worker look into the problem, I finally, in a flash of genius, discovered the answer.
At some point when I was refactoring the code, I changed the function to get rid of the Value parameter, leaving it as follows:
Public Function GetSomeStringValue() As String
... Code Goes here
Return Some_Multicharacter_String
End Function
However, I neglected to remove the parameter that I was passing in when calling the function:
SomeStringValue = GetSomeStringValue(Value)
The compiler didn't complain because it interpreted what I was doing as calling the function without brackets, which is a legacy feature from the VB6 days. Then, the Value parameter transformed into the array index of the string (aka character array) that was returned from the function.
So I removed the parameter, and everything worked fine:
SomeStringValue = GetSomeStringValue()
I'm posting this so that other people will recognize the problem when/if they ever encounter it, and are able to solve it much more quickly than I did. It took quite a while for me to solve, and I hope I can save others some time.