Wrapping Stopwatch Timing with a Delegate or Lambda

Wrapping StopWatch timing with a delegate or lambda?

How about extending the Stopwatch class?

public static class StopwatchExtensions
{
public static long Time(this Stopwatch sw, Action action, int iterations)
{
sw.Reset();
sw.Start();
for (int i = 0; i < iterations; i++)
{
action();
}
sw.Stop();

return sw.ElapsedMilliseconds;
}
}

Then call it like this:

var s = new Stopwatch();
Console.WriteLine(s.Time(() => DoStuff(), 1000));

You could add another overload which omits the "iterations" parameter and calls this version with some default value (like 1000).

Can I tie an anonymous function to a Timer's tick event?

You're looking for Anonymous Methods:

myTimer.Tick += delegate (object sender, EventArgs e) {
MessageBox.Show("Hello world!");
};

You can also omit the parameters:

myTimer.Tick += delegate {
MessageBox.Show("Hello world!");
};

In C# 3.0, you can also use a Lambda Expression:

myTimer.Tick += (sender, e) => {
MessageBox.Show("Hello world!");
};

Helper class for performance tests using StopWatch class

Here is simple class, which can help you for measuring time of code block execution:

public class PerformanceTester : IDisposable
{
private Stopwatch _stopwatch = new Stopwatch();
private Action<TimeSpan> _callback;

public PerformanceTester()
{
_stopwatch.Start();
}

public PerformanceTester(Action<TimeSpan> callback) : this()
{
_callback = callback;
}

public static PerformanceTester Start(Action<TimeSpan> callback)
{
return new PerformanceTester(callback);
}

public void Dispose()
{
_stopwatch.Stop();
if (_callback != null)
_callback(Result);
}

public TimeSpan Result
{
get { return _stopwatch.Elapsed; }
}
}

Usage (just wrap code block with using of PerformanceTester):

using (var tester = new PerformanceTester())
{
// code to test
MessageBox.Show(tester.Results.ToString());
}

If you declare tester variable before using block, then stopwatch will stop automatically when you exit using block, and results will be available for you:

PerformanceTester tester;

using (tester = new PerformanceTester())
SomeAction();

MessageBox.Show(tester.Results.ToString());

If you pass callback action to PerformanceTester, then this action will be called at the end of using statement, and elapsed time will be passed to callback:

using (PerformanceTester.Start(ts => MessageBox.Show(ts.ToString())))
SomeAction();

You can declare method, which will accept TimeSpan and process results:

private void ProcessResult(TimeSpan span)
{
// log, show, etc
MessageBox.Show(span.ToString());
}

Usage becomes very clean:

using (PerformanceTester.Start(ProcessResult))
SomeAction();

Wrap a delegate in an IEqualityComparer

Ordinarily, I'd get this resolved by commenting @Sam on the answer (I've done some editing on the original post to clean it up a bit without altering the behavior.)

The following is my riff of @Sam's answer, with a [IMNSHO] critical fix to the default hashing policy:-

class FuncEqualityComparer<T> : IEqualityComparer<T>
{
readonly Func<T, T, bool> _comparer;
readonly Func<T, int> _hash;

public FuncEqualityComparer( Func<T, T, bool> comparer )
: this( comparer, t => 0 ) // NB Cannot assume anything about how e.g., t.GetHashCode() interacts with the comparer's behavior
{
}

public FuncEqualityComparer( Func<T, T, bool> comparer, Func<T, int> hash )
{
_comparer = comparer;
_hash = hash;
}

public bool Equals( T x, T y )
{
return _comparer( x, y );
}

public int GetHashCode( T obj )
{
return _hash( obj );
}
}

Make a method to return Execution Time of another Method

I've just created such a method to test performance in this SO question:

private static TimeSpan MeasureExecTime(Action action, int iterations)
{
action(); // warm up
var sw = Stopwatch.StartNew();
for (int i = 0; i < iterations; i++)
{
action();
}
return sw.Elapsed;
}

Usage:

MeasureExecTime(() => DoSomething(5), 100000);

See 280Z28's answer if you don't want to test more than one iteration :-)

Store function for later use / delegate with undefined attributes

Whenever you need a delegate with unknown signature simply wrap it inside of an Action (basically a parameter less void delegate)

You could probably do something like

// For storing the callback
private Action _whenHaveAuthority;
// For storing the NetworkIdentity that requested authority
// In order to check back later if the event is for us
private NetworkIdentity _identity;

public void RequestAuthority(NetworkIdentity identity, Action whenHaveAuthority)
{
// Store identity and callback
_whenHaveAuthority = whenHaveAuthority;
_identity = identity;
CmdRequestNetworkAuthority(identity);
}

[Command]
private void CmdRequestNetworkAuthority(NetworkIdentity identity)
{
identity.AssignClientAuthority(base.connectionToClient);

Rpc_InformClientHasAuthority(identity);
}

// Server informs all clients
[ClientRpc]
private void Rpc_InformClientHasAuthority(NetworkIdentity identity)
{
// Check if we are the one that sent the request
if(_identity && _identity == identity)
{
// Execute the stored callback
_whenHaveAuthority?.Invoke();

// and reset
_identity = null;
_whenHaveAuthority = null;
}
}

And then you would pass in the callback like e.g.

public void CornerSpawnRequest(Vector3 spawnPosition, GameObject joinToObject)
{
NetworkIDRequest.instance.RequestAuthority(GetComponent<NetworkIdentity>(), () =>
{
NetworkCornerSpawn(spawnPosition, joinToObject);
});
}

[Command]
private void NetworkCornerSpawn(Vector3 spawnPosition, GameObject joinToObject)
{
CornerSpawnExecution(spawnPosition, joinToObject);
}

Note: Typed on smartphone but I hope the idea gets clear



Related Topics



Leave a reply



Submit