Closure and capturing local variable in a loop - c#

using System;
public class Program
{
public static void Main()
{
IRunnable runnable = new Runnable();
for(int i=0;i<10;i++)
{
RunIt(runnable);
}
}
public static void RunIt(IRunnable runnable)
{
var context = new Context();
context.Id = runnable.RunAsync((id,result)=>{
//context.Id will always match "id" here?
context.Result = result; // can I assume here that this is the same context?
});
}
public interface IRunnable
{
int RunAsync(Action<string,string> successHandler);
}
public class Runnable : IRunnable
{
private Random _random = new Random();
public string RunAsync(Action<string,string> successHandler)
{
var guid = Guid.NewGuid().ToString();
Task.Run(()=>
{
Thread.Sleep(_random.Next(0,1000));
successHandler(guid, "result")
});
return guid;
}
}
public class Context
{
public string Id {get;set;}
public string Result{get;set;}
}
}
In this example I'm running function RunIt in a loop. RunIt starts a process asynchronously and assign anonymous handler when it's done. In the same function we have a context variable which will be captured by anonymous lambda. My question is simple - can I assume that captured context will always match the result? My concern here is that I'm running it 10 times which means successHandler will be called 10 times in unordered manner. Is there a separate version of anonymous function per each context?
Long story short - will context.Id always match successHandler "id" in anonymous function?

I know this question was downvoted but I'll answer it anyway. The answer is yes, Context variable will be captured separately per each iteration.

Related

Is it safe for Task.Run() to access Method scope variables?

Is the following guaranteed to print "Success," or is it possible garbage collection can eat the "dummyValue" object since TaskTest() ends long before the task it returns can finish?
public class DummyValueClass
{
public string Value { get; private set; }
public DummyValueClass(string value)
{
Value = value;
}
}
public class ScopeTest
{
public Task<string> TaskTest()
{
var dummyValue = new DummyValueClass("Success");
return Task.Run(() =>
{
Thread.Sleep(10000);
return dummyValue?.Value;
});
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Beginning Test");
var scopeTester = new ScopeTest();
var task = scopeTester.TaskTest();
Console.WriteLine(task.Result);
}
}
This is called a closure.
var dummyValue = new DummyValueClass("Success");
return Task.Run(() =>
{
Thread.Sleep(10000);
return dummyValue?.Value;
});
In short the compiler creates a compiler generate class and captures dummyValue as an instance member.
Example of sanitized emitted code. You can view all the gory details here
public class ScopeTest
{
[CompilerGenerated]
private sealed class GeneratedClass
{
public DummyValueClass dummyValue;
internal string InternalTaskTest()
{
Thread.Sleep(10000);
DummyValueClass dummyValueClass = dummyValue;
if (dummyValueClass == null)
{
return null;
}
return dummyValueClass.Value;
}
}
public Task<string> TaskTest()
{
GeneratedClass generatedClass = new GeneratedClass();
generatedClass.dummyValue = new DummyValueClass("Success");
return Task.Run(new Func<string>(generatedClass.InternalTaskTest));
}
}
The task now has a method pointer to the generated method, which in turn roots the GeneratedClass which has a reference to your DummyValueClass. The result being that the Garbage Collector knows your reference is still alive.
Yes, it is guaranteed to print "Success". Because when a lambda captures value outside from its scope, the compiler will generate an object which "captures" the variables acquired from outside its scope. So it will not be garbage collected

C# Trying to wrap a function with a stopwatch

I've been attempting to see how long functions take to execute in my code as practice to see where I can optimize. Right now I use a helper class that is essentially a stopwatch with a message to check these. The goal of this is that I should be able to wrap whatever method call I want in the helper and I'll get it's duration.
public class StopwatcherData
{
public long Time { get; set; }
public string Message { get; set; }
public StopwatcherData(long time, string message)
{
Time = time;
Message = message;
}
}
public class Stopwatcher
{
public delegate void CompletedCallBack(string result);
public static List<StopwatcherData> Data { get; set; }
private static Stopwatch stopwatch { get; set;}
public Stopwatcher()
{
Data = new List<StopwatcherData>();
stopwatch = new Stopwatch();
stopwatch.Start();
}
public static void Click(string message)
{
Data.Add(new StopwatcherData(stopwatch.ElapsedMilliseconds, message));
}
public static void Reset()
{
stopwatch.Reset();
stopwatch.Start();
}
}
Right now to use this, I have to call the Reset before the function I want so that the timer is restarted, and then call the click after it.
Stopwatcher.Reset()
MyFunction();
Stopwatcher.Click("MyFunction");
I've read a bit about delegates and actions, but I'm unsure of how to apply them to this situation. Ideally, I would pass the function as part of the Stopwatcher call.
//End Goal:
Stopwatcher.Track(MyFunction(), "MyFunction Time");
Any help is welcome.
It's not really a good idea to profile your application like that, but if you insist, you can at least make some improvements.
First, don't reuse Stopwatch, just create new every time you need.
Second, you need to handle two cases - one when delegate you pass returns value and one when it does not.
Since your Track method is static - it's a common practice to make it thread safe. Non-thread-safe static methods are quite bad idea. For that you can store your messages in a thread-safe collection like ConcurrentBag, or just use lock every time you add item to your list.
In the end you can have something like this:
public class Stopwatcher {
private static readonly ConcurrentBag<StopwatcherData> _data = new ConcurrentBag<StopwatcherData>();
public static void Track(Action action, string message) {
var w = Stopwatch.StartNew();
try {
action();
}
finally {
w.Stop();
_data.Add(new StopwatcherData(w.ElapsedMilliseconds, message));
}
}
public static T Track<T>(Func<T> func, string message) {
var w = Stopwatch.StartNew();
try {
return func();
}
finally {
w.Stop();
_data.Add(new StopwatcherData(w.ElapsedMilliseconds, message));
}
}
}
And use it like this:
Stopwatcher.Track(() => SomeAction(param1), "test");
bool result = Stopwatcher.Track(() => SomeFunc(param2), "test");
If you are going to use that with async delegates (which return Task or Task<T>) - you need to add two more overloads for that case.
Yes, you can create a timer function that accepts any action as a delegate. Try this block:
public static long TimeAction(Action action)
{
var timer = new Stopwatch();
timer.Start();
action();
timer.Stop();
return timer.ElapsedMilliseconds;
}
This can be used like this:
var elapsedMilliseconds = TimeAction(() => MyFunc(param1, param2));
This is a bit more awkward if your wrapped function returns a value, but you can deal with this by assigning a variable from within the closure, like this:
bool isSuccess ;
var elapsedMilliseconds = TimeToAction(() => {
isSuccess = MyFunc(param1, param2);
});
I've had this problem a while ago as well and was always afraid of the case that I'll leave errors when I change Stopwatcher.Track(() => SomeFunc(), "test")(See Evk's answer) back to SomeFunc(). So I tought about something that wraps it without changing it!
I came up with a using, which is for sure not the intended purpose.
public class OneTimeStopwatch : IDisposable
{
private string _logPath = "C:\\Temp\\OneTimeStopwatch.log";
private readonly string _itemname;
private System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
public OneTimeStopwatch(string itemname)
{
_itemname = itemname;
sw.Start();
}
public void Dispose()
{
sw.Stop();
System.IO.File.AppendAllText(_logPath, string.Format($"{_itemname}: {sw.ElapsedMilliseconds}ms{Environment.NewLine}"));
}
}
This can be used a easy way
using (new OneTimeStopwatch("test"))
{
//some sensible code not to touch
System.Threading.Thread.Sleep(1000);
}
//logfile with line "test: 1000ms"
I only need to remove 2 lines (and auto format) to make it normal again.
Plus I can easily wrap multiple lines here which isn't possible without defining new functions in the other approach.
Again, this is not recommended for terms of few miliseconds.

Setting a class property on a long running thread

I am populating some class properties,
One of them involves serializing an Entity structure to a byte[] this takes some time so I wanted to do it in a thread.
The value never gets set as I assume the class and thread are now out of scope.
The code is below, any ideas would be appreciated
public class classA
{
public void DoSomething()
{
var classC = new ClassB().DoSomethingElse();
//SAVE CLASS c to database
var serialized = classC.GetSerializedDataTable(); // is always null unless i take out the task from class c
}
}
public class ClassB
{
public ClassC DoSomethingElse()
{
var classC = new ClassC();
classC.DataTableValue = new DataTable();
classC.SerializeToByteArray();
return classC;
}
}
public class ClassC
{
public DataTable DataTableValue { get; set; }
private byte[] serializedData;
public void SerializedDataTable()
{
new Task(() => this.serializedData = this.DataTableValue.SerializeToByteArray()).Start();
}
public byte[] GetSerializedDataTable()
{
return this.serializedData;
}
}
A Task is not just meant to be used to run code on another thread, it represents a logical unit of work that can return something once it is complete.
Your ClassC.GetSerializedDataTable() appears to be a perfect place to make use of a Task<byte[]> return type:
public class ClassC
{
public DataTable DataTableValue { get; set; }
private Task<byte[]> serializeDataTask;
public void SerializeDataTable()
{
serializeDataTask = Task.Factory.StartNew( () => this.DataTableValue.SerializeToByteArray() );
}
public Task<byte[]> GetSerializedDataTable()
{
// You can either throw or start it lazily if SerializeDataTable hasnt been called yet.
if ( serializeDataTask == null )
throw new InvalidOperationException();
return serializeDataTask;
}
}
And now your client code can utilize the Task return type in intelligent ways. If the result is already available, it can consume it immediately via Task.Result. Otherwise it can wait for it to complete, or perform some other work until it completes. The point is the calling code now has the context to take the most appropriate course of action.
Back to your example:
public void DoSomething()
{
var classC = new ClassB().DoSomethingElse();
//SAVE CLASS c to database
var serializeTask = classC.GetSerializedDataTable();
// will obtain result if available, will block current thread and wait for serialized data if task still running.
var serializedData = serializeTask.Result;
}

Ref in async Task

How I can to pass a reference as a parameter to Async method in Windows Store App ? I'm looking for something like this:
var a = DoThis(ref obj.value);
public async Task DoThis(ref int value)
{
value = 10;
}
But error:
Async methods cannot have ref or out parameters
Has any another way?
Note:I need to pass exactly obj.value. This method would be used by different types of objects, by same type of objects, by one object, but I will pass obj.val_1, obj.val_2 or obj.val_10. All values will be same type (for ex string)
If you don't care about a little overhead and possibly prolonged lifetime of your objects, you could emulate the ref behavior by passing a setter and a getter method to the function, like this:
public async Task DoStuff(Func<int> getter, Action<int> setter)
{
var value1 = getter();
await DoSomeOtherAsyncStuff();
setter(value1 * value1);
}
And call it like this:
await DoStuff(() => obj.Value, x => obj.Value = x);
You could directly pass the object itself and set the value of the corresponding property inside the method:
var a = DoThis(obj);
public async Task DoThis(SomeObject o)
{
o.value = 10;
}
And if you do not have such object simply write one and have the async method take that object as parameter:
public class SomeObject
{
public int Value { get; set; }
}
You can always use the Task<> class and return the desired value. Then Your code would look something like:
var a = DoThis(obj.value);
obj.value = a.Result;
public async Task<int> DoThis(int value)
{
int result = value + 10; //compute the resulting value
return result;
}
EDIT
Ok, the other way to go with this that I can think of is encapsulating the update of the given object's member in a method and then passing an action invoking this method as the task's argument, like so:
var a = DoThis(() => ChangeValue(ref obj.value));
public void ChangeValue(ref int val)
{
val = 10;
}
public async Task DoThis(Action act)
{
var t = new Task(act);
t.Start();
await t;
}
As far as I tested it the change was made in the child thread, but still it's effect was visible in the parent thread. Hope this helps You.
You can't do this as you have it (as you know). So, a few work arounds:
You can do this by passing the initial object since it will be a reference type
var a = DoThis(obj);
public async Task DoThis(object obj) //replace the object with the actual object type
{
obj.value = 10;
}
EDIT
Based upon your comments, create an interface and have your classes implement it (providing it's always the same type you want to pass). Then you can pass the interface which is shared (maybe over kill, depends on your needs, or even unrealistic amount of work).
Or, provide a base class with the property! (I don't like this suggestion but since you're asking for something which can't be done it may suffice although I don't recommend it).
An example of the interface is here (not using what you have, but close enough using a Colsone App)
using System;
namespace InterfacesReferenceTypes
{
class Program
{
static void Main(string[] args)
{
MyClass mc = new MyClass();
DoThis(mc);
Console.WriteLine(mc.Number);
Console.ReadKey();
}
static void DoThis(IDemo id)
{
id.Number = 10;
}
}
class MyClass : IDemo
{
//other props and methods etc
public int Number { get; set; }
}
interface IDemo
{
int Number { get; set; }
}
}
EDIT2
After next comments, you will have to still use an interface, but re assign the value afterwards. I'm sure there is a better way to do this, but this works:
using System.Text;
namespace InterfacesRerefenceTypes
{
class Program
{
static void Main(string[] args)
{
MyClass mc = new MyClass();
Console.WriteLine(mc.Number);
mc.val1 = 3;
mc.val2 = 5;
mc.Number = mc.val2;
DoThis(mc);
mc.val2 = mc.Number;
Console.WriteLine(mc.val2);
Console.ReadKey();
}
static void DoThis(IDemo id)
{
id.Number = 15;
}
}
class MyClass : IDemo
{
public int val1 { get; set; }
public int val2 { get; set; }
public int Number { get; set; }
}
interface IDemo
{
int Number { get; set; }
}
}

Incrementing a unique ID number in the constructor

I'm working on an object in C# where I need each instance of the object to have a unique id. My solution to this was simply to place a member variable I call idCount in the class and within the constructor I would have:
objectID = idCount;
idCount++;
I thought that this would solve my problem but it seems that idCount never gets incremented even though the constructor gets called multiple times. For example if idCount = 1, the objectID for all the objects are still 1. Why doesn't idCount++ work?
Any help would be appreciated. Apologies if my explanation isn't adequate, I'm not sure how else to explain it.
You need a static property in your class, BUT, you need to assign it to an instance variable within the class if you want each object to contain the id it was created with.
Also, you'll want to use Interlocked.Increment on the counter in case you are updating multiple instances simultaneously:
public class Foo
{
private static int m_Counter = 0;
public int Id { get; set; }
public Foo()
{
this.Id = System.Threading.Interlocked.Increment(ref m_Counter);
}
}
You could use a static variable in your class that gets updated when the object is initialized.
public class Foo
{
private static int ID = 0;
private int myId = 0;
public int MyId
{
get { return myId; }
}
public Foo()
{
ID++;
this.myId = ID;
}
}
As everyone has pointed out, static variables are the specific answer to your question. But static variables only have scope within the process in which they were created and there is no relationship across processes (for example, a load balanced web environment).
If what you are looking for is a unique way to identify an object instance for the duration of its lifetime, I suggest something like:
byte[] bytes = new byte[8];
RNGCryptoServiceProvider crypto = new RNGCryptoServiceProvider();
crypto .GetBytes( bytes );
long id = BitConverter.ToInt64( bytes, 0 );
This will give you a random number which has an extremely low (roughly 0-1 in 100,000,000) chance of collision and you don't need to worry about keeping track of it.
You set IdCount is static member of MyObject.
public class MyObject
{
static int idCount = 0;
private int _objectID;
public int ObjectID
{
get { return _objectID; }
}
public MyObject()
{
idCount++;
_objectID = idCount;
}
}
public sealed class SingletonIdGenerator
{
private static long _id;
private SingletonIdGenerator()
{
}
public string Id
{
get { return _id++.ToString().Substring(8); }
}
public static SingletonIdGenerator Instance { get { return Nested.instance; } }
private class Nested
{
static Nested()
{
_id = DateTime.Now.Ticks;
}
internal static readonly SingletonIdGenerator instance = new SingletonIdGenerator();
}
}

Categories

Resources