In the following code, which is better? To call add page from within CardPanelDesigner_AddPage? Or use the Func TransactionFunction??
Basically I want to know if doing the inner func will create a "new function" every time :S I don't even know what I'm asking.
Is there an overhead to doing the inner function or should I use the addpage?
private object AddPage(IDesignerHost Host, object Sender)
{
return null;
}
private void CardPanelDesigner_AddPage(object sender, EventArgs e)
{
IDesignerHost DesignerHost = (IDesignerHost)GetService(typeof(IDesignerHost));
if (DesignerHost != null)
{
Func<IDesignerHost, object, object> TransactionFunction = (Host, Param) =>
{
return null;
};
TransactionInfo("Add Page", DesignerHost, AddPage); //Add page? OR TransactionFunction? :S
}
}
Yes, TransactionFunction will create a new object each time CardPanelDesigner_AddPage is called. The performance overhead of this however will likely be negligible. You should do whatever reads best to you (and your team).
Related
My project is WPF application.
I have a class for example Products having multiple properties(string , int, List<>). I am looking to cache this object in memory (not in file), and use it.
Also looking for event raised when cache object is updated similarly as HostFileChangeMonitor.
The reason why I am looking for above solution is:
I have to send current object to third party dll (which is on timer of 5 sec) and it is heavy object which hampering performance of GUI.
Hence by caching class object, I will monitor to call this heavy operation ONLY WHEN cache object is updated.
I already thought to save object properties value to txt file and use HostFileChangeMonitor to trigger event, but this will add one more IO operation.
Please share if any inputs?
Thanks all to view my question. Finally I got working code with time specific memory cache.
Posting it may be it is useful for someone like me. It is explained with an example.
private MemoryCache mc = new MemoryCache("CacheProvider"); // Creating memory cache object.
public MainWindow()
{
InitializeComponent();
}
// Method to get cache elements.
private void GetCache_Click(object sender, RoutedEventArgs e)
{
lstEmployeeID.Items.Clear();
lstEmployeeName.Items.Clear();
var emp = new Employee();
foreach (Employee emp1 in emp.GetEmployeeList())
{
var cacheObj = mc[emp1.EmployeeName] as Employee; // typecasting it class object.
if (cacheObj != null)
{
lstEmployeeID.Items.Add(cacheObj.EmployeeId);
lstEmployeeName.Items.Add(cacheObj.EmployeeName);
}
}
}
// Saving class object to cache.
private void SaveCache_Click(object sender, RoutedEventArgs e)
{
var emp = new Employee();
var policy = new CacheItemPolicy();
policy.AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(10.0);
foreach (Employee emp1 in emp.GetEmployeeList())
{
mc.Add(emp1.EmployeeName, emp1, policy); // adding (key, objectItem, CachingPolicy)
}
}
Before C#6, i was using this routine to deal with generating events in a multi threaded program: (i found it somewhere, but can't remember where):
public static object Raise(this MulticastDelegate multicastDelegate, object sender, EventArgs e)
{
object retVal = null;
MulticastDelegate threadSafeMulticastDelegate = multicastDelegate;
if (threadSafeMulticastDelegate != null)
{
foreach (Delegate d in threadSafeMulticastDelegate.GetInvocationList())
{
var synchronizeInvoke = d.Target as ISynchronizeInvoke;
if ((synchronizeInvoke != null) && synchronizeInvoke.InvokeRequired)
retVal = synchronizeInvoke.EndInvoke(synchronizeInvoke.BeginInvoke(d, new[] { sender, e }));
else
retVal = d.DynamicInvoke(sender, e);
}
}
return retVal;
}
so all i had to do was Eventname.Raise(...,....)
now with C#6, i know the new was it using something like:
Eventname?.Invoke(...);
what i am wondering is, should i change all my event creations to Invoke as it works different to the Raise(), or is it the same thing ?
You should never have been using that method in the first place. It's way too complicated. Instead, something like this would have been better:
public static void Raise(this Delegate handler, object sender, EventArgs e)
{
if (handler != null)
{
handler.DynamicInvoke(sender, e);
}
}
As for whether you should change your event-raising code, I'd say no. Not unless you've got a lot of time to kill and like going through your entire code base replacing perfectly good code.
What you should do is fix your current Raise() method. And feel free for any new code to write it the new C# 6 way, i.e. MyEvent?.DynamicInvoke(this, EventArgs.Empty) (which effectively amounts to the exact same thing as MyEvent.Raise(this, EventArgs.Empty) using the above, except without the extra method call).
I've got some code like this:
private void button1_Click(object sender, EventArgs e)
{
Someclass object= new Someclass();
foreach (conditioin)
{
some methods();
}
object= null;
}
I need to free memory of object becuase every time that I press the button it shows me the same results. But methods inside should be forget and initialised with new result all over again.
Can you help me, please?
$$ UPDATE $$
OK so I'll provide the specific code
I use NativeWiFi
private void button1_Click(object sender, EventArgs e)
{
listView1.Items.Clear();
WlanClient client = new WlanClient();
foreach (WlanClient.WlanInterface wlanIface in client.Interfaces)
{
Wlan.WlanBssEntry[] wlanBssEntries = wlanIface.GetNetworkBssList();
foreach (Wlan.WlanBssEntry network in wlanBssEntries)
{
byte[] macAddr = network.dot11Bssid;
string tMac = "";
for (int i = 0; i < macAddr.Length; i++)
{
tMac += macAddr[i].ToString("x2").PadLeft(2, '0').ToUpper();
}
listView1.Items.Add(String.Format("{0} Signal: {1}% ", (GetStringForSSID(network.dot11Ssid)), network.linkQuality));
/*
Console.WriteLine("Signal: {0}%.", network.linkQuality);
Console.WriteLine("BSS Type: {0}.", network.dot11BssType);
Console.WriteLine("MAC: {0}.", tMac);
Console.WriteLine("");*/
}
}
client = null;
}
static string GetStringForSSID(Wlan.Dot11Ssid ssid)
{
return System.Text.Encoding.ASCII.GetString(ssid.SSID, 0, (int)ssid.SSIDLength);
}
It is a common misunderstanding that setting a local variable to null frees up any memory. As the variable goes out of scope when leaving the method anyway, the object = null; line doesn't make any sense.
Also in .NET you can not force memory to be freed. The garbage collection does its job whenever it thinks it's time.
Generally spoken, every time you execute the constructor Someclass() a new object is created. In plain C# the location in memory is irrelevant. All members will be initialized, either implicitly e.g. to null or by your own code. If you obtain the same results in each loop iteration that is because the initialization is the same as in the previous runs.
"Cross-thread operation is not valid" exception
I experienced this exception many times, but all those times I was setting the value of a control. That time I solved using a function called SetControlPropertyThreadSafe(), which was suggested by someone on stackoverflow.com only. But this time I am getting this exception when I am trying to get the value of comboBox. Here is the code:
string cat;
private void button1_Click(object sender, EventArgs e)
{
if (textBox1.Text.Trim().Length > 20)
{
System.Threading.Thread t = new System.Threading.Thread(addQuickTopic);
t.Start();
}
else
MessageBox.Show("The length of the title must be greater than 20", "Title length invalid", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
public string tTitle="";
void addQuickTopic()
{
Global.SetControlPropertyThreadSafe(button1, "Text", "Working...");
Global.SetControlPropertyThreadSafe(button1, "Enabled", false);
Topic t = new Topic();
t.setTitle(textBox1.Text);
t.setDescription(" ");
t.setDesID(Global.getMd5Hash(Common.uid+DateTime.Today.ToString()+DateTime.Today.Millisecond.ToString()));
t.setUsrID(Common.uid);
t.setReplyToID("");
t.setConDate("0");
cat = CategoryList.SelectedValue.ToString();
As you can see I am getting the textBox1.Text directly without applying any thread safe operation. But at the last line when trying to fetch comboBox's selected value, I am getting this exception. So can any one please suggest me what to do in this situation? Following is the code for my thread safe function for setting control's value:
public static void SetControlPropertyThreadSafe(Control control, string propertyName, object propertyValue)
{
try
{
if (control.InvokeRequired)
{
control.Invoke(new SetControlPropertyThreadSafeDelegate(SetControlPropertyThreadSafe), new object[] { control, propertyName, propertyValue });
}
else
{
control.GetType().InvokeMember(propertyName, BindingFlags.SetProperty, null, control, new object[] { propertyValue });
}
}
catch (Exception)
{ }
}
Should I need to create a similar get function? Or any other solution available?
Right now, you're getting the value from the TextBox, via: t.setTitle(textBox1.Text);. This will also fail.
Should I need to create a similar get function? Or any other solution available?
Yes, you need an option for get. I would recommend not using reflection and text, however, and rework this to use generic methods and lambdas.
public static void SetControlPropertyThreadSafe<T>(T control, Action<T> action) where T : Control
{
if (control.InvokeRequired)
{
control.Invoke(action);
}
else
{
action();
}
}
This would allow you to write this strongly typed, ie:
Global.SetControlPropertyThreadSafe(button1, b => b.Text = "Working...");
You can also make a strongly typed get method:
public static U GetControlPropertyThreadSafe<T,U>(T control, Func<T,U> func) where T : Control
{
if (control.InvokeRequired)
{
return (U)control.Invoke(func, new object[] {control});
}
else
{
return func(control);
}
}
Which then lets you write:
t.setTitle(Global.GetControlPropertyThreadSafe(textBox1, t => t.Text));
You could also use the same methods for getting and setting the combo box items.
You need a similar get function, which calls Invoke if required.
This depends from the threading model of the GUI, which states that all the methods that interact with the GUI should only be called by the GUI thread.
It's not important if you're trying to read, to write, or do anything else. If you're not on the GUI thread, you must use Invoke.
depending on the do work method my result could either be a List of Strings or a list of byte[]
How can we check the RunWorkerCompletedEventArgs e -
if (e is List<String>)
is this the correct way to check?
No, this is not the right way.
The correct way is to use this:
if(e.Result is List<string>)
{
//...
}
else if(e.Result is List<byte[]>)
{
//...
}
else
{
//...
}
e will always be of type RunWorkerCompletedEventArgs. But this class contains a property Result that contains the result of your DoWork event handler. That's the one, you need to check.
Yes, that's one possible way to do it.
If you only have two types it would be quite easy:
if(e.Result is List<string>)
{
}
else if(e.Result is List<byte[]>)
{
}
else
{
}
But the problem comes in to play if you have to support more than just two or three. In that case i'm going to create a Dictionary<Type, Action<object>> and write individual functions for each type. Something like this:
var supportedTypes = new Dictionary<Type, Action<object>>();
supportedTypes.Add(typeof(List<string>), ComputeListOfStrings);
supportedTypes.Add(typeof(List<byte[]>), ComputeListOfByteArrays);
private void ComputeListOfString(object listOfStrings)
{
var list = (List<string>)listOfStrings;
}
private void ComputeListOfByteArrays(object listOfByteArrays)
{
var list = (List<byte[]>)listOfByteArrays;
}
This makes it more simple to support new types and also stays to be O(1) while the if-else-if runs into the order-matters problem.
Used will this in your background worker as followed:
worker.OnRunWorkerCompleted += (sender, e) =>
{
Action<object> supportedAction;
supportedTypes.TryGetValue(e.Result.GetType(), out supportedAction);
if(supportedAction != null)
{
supportedAction();
}
};
the e.Result is the property with your results, so to get the type you can do:
if(e.Result.GetType().Equals(typeof(List<String>)))