I am debugging a WCF project with two-way communication. I have a callback with data that I store in an array the client, a WinForm, and use that for painting a control. As you can guess, the data disappears from writing in the array (really a list) to when I read the data.
For debugging I would like to see if I am writing and reading the same object so that the callback function isn't making some kind of copy and throw it away. For example I want to see the address of the this - pointer. How do I do that in VS2010 Exp?
Edit
Some code:
Field declaration:
// the cards that the player have
private List<Card> cards = new List<Card>();
callback handler:
private void btnDraw_Click(object sender, EventArgs e)
{
Tuple<Card, string> update = PressedDraw(this);
cards.Add(update.Item1);
PaintCards();
}
paint event:
private void cardPanel_Paint(object sender, PaintEventArgs e)
{
int counter = 0;
Point fromCorner = new Point(20,12);
int distance = 50;
foreach (Card card in cards)
{
Point pos = fromCorner;
pos.Offset(counter++ * distance, 0);
Bitmap cardBitmap =
cardFaces[Convert.ToInt32(card.suit),
Convert.ToInt32(card.rank)];
Rectangle square = new Rectangle(pos, cardBitmap.Size);
e.Graphics.DrawImage(cardBitmap, square);
}
When I debug I enter first in the callback handler and adds a Card in cards
PaintCards() calls Invalidate and the paint event is run. When in cardPanel_Paint, cards.Count is zero again.
Best regards.
Görgen
In the Watch/Locals/Autos windows, you can right-click on an object and select "Make Object ID" to give the object an identification number. This number is effectively the same as a native object's address; it serves to identify.
The identity of an object is tracked across garbage collections and compactions, so across the lifetime of your application, you can tell if a certain object is the one you originally tagged. This feature might help in your situation.
This blog post has a quick run-through of the feature.
The address of an object in c# can be changed by the garbage collector so you can not use that (and there is no straight forward method to do so).
But you can use Object.ReferenceEquals to compare to objects to see if they are really the same.
Edit:
But it looks like you have messed things up something like this.
var a = new List<string> { "String1" };
var b = a;
a = new List<string> { "String 2" }; // really GetListFromWcf();
Console.WriteLine(b[0]);
this prints String1, not String2.
If you can not figure it out you need to post some code to show where thing get wrong.
Related
I have a program that runs in the system tray that communicates with our server and "syncs" data based on a users preferenced jobs. The idea is similar to Dropbox, but for our surveying software called 12d Synergy. The idea is that users can sync data without needing to navigate through the softwares Client.
I want to add the functionality so that when the program is syncing, the icon in the system tray changes to indicate that its still syncing, but i can't figure out how to get access to the original object within the portion of the program where the event is located.
My program stucture is as follows (in c#):
Program.cs
using (ProcessingIcon pi = new ProcessingIcon())
{
pi.SetIcon(Resources._12d);
pi.Display();
Application.Run();
}
ProcessingIcon.cs
NotifyIcon ni;
public void SetIcon(Icon path)
{
ni.Icon = path;
}
public void Display()
{
ni.Text = "Sunrise Surveying 12d Synergy Sync Tool";
ni.Visible = true;
ni.ContextMenuStrip = new ContextMenus().Create();
}
ContextMenus.cs
public ContextMenuStrip Create()
{
// Sync Now
item = new ToolStripMenuItem();
item.Text = "Sync Now";
item.Click += new EventHandler(syncNow_Click);
item.Image = Resources.Sync.ToBitmap();
cms.Items.Add(item);
}
void syncNow_Click(object sender, EventArgs e)
{
string[] jobs = Sync.GetSharedFiles();
string[] files = Sync.GetDataToSync(jobs);
Sync.SyncData(files);
}
What i want to happen, is in the syncNow_click, call the ProcessingIcon.SetIcon() to change the icon, but i can't figure out how to get access to an object that exists 3 layers up in the program.
I should note that i am not a programmer, i'm a surveyor with an interest in programming. I am completely self taught, so i know there is probably something relatively simple i'm missing. This is also my first post in StackOverflow, so i'm not 100% how to use this site to the full capability, so if this has been answered somewhere i apologise.
Any help or advice would be greatly appreciated.
So i worked out a way to answer my own question. Just putting it here in case anyone has the same issue. It turned out to be incredibly simple, and purely just by me not fully understanding the classes/objects structure.
I added a constructor for my ContextMenus object which passed in the the NotifyIcon that was calling it. This was passed to a NotifyIcon variable in that class which i could then access.
class ContextMenus
{
public NotifyIcon ni;
public ContextMenus(NotifyIcon ni)
{
this.ni = ni;
}
}
I'm modifying existing C# code in order to pilote a piston. Every 30ms, I have a direct feedback of the position of this piston, through an event. The value is stored in a global variable I use to get the current position of the piston.
What I'm trying to achieve: for a given distance input (A->C), I want the piston to travel at full speed for 95% of the distance (A->B), and then slower for the remaining 5% (B->C).
I have access to a command that defines the speed and the destination of the piston : pos(velocity, destination).
However, if I write that code:
pos(fullSpeed,B);
pos(reducedSpeed, C);
the piston directly goes from fullSpeed to reducedSpeed
I tried to use a while loop to compare the current position of the piston with the goal destination, however, upon entering the while loop, the variable storing the piston position does not update anymore.
However, I noticed that by throwing a MessageBox in between, the position value keeps on getting updated, and I can simply click "ok" to launch the second command.
pos(fullSpeed,B);
MessageBox.show("Wait");
pos(reducedSpeed, C);
I would like to know why the "while" loop stops the update of the position variable but the MessageBox does not. I mean, as long as I don't click the "ok" button, the box is here preventing me from doing anything, which for me ressembles a while loop behaviour. Is there another way for me to do this instead of the MessageBox ?
I have little to no knowledge when it comes to C# and no support. I have tried to look in the documentation, but I did not find an answer (I have probably missed it). Any lead is more than welcome.
EDIT: I have no documentation for that code, and it is barely commented. Here is what I gathered (really hope it helps):
To move the piston, taht function is called:
MyEdc.Move.Pos(control, speed, destination, ref MyTan);
control simply define what we pilote (a distance or a load, it is an enum), and I have no idea what MyTan does. Only thing I know is that the MyEdc.Move.Pos returns an error code.
If I look at the definition of "pos", I am redirected to class
public DoPEmove Move;
containing among other things:
public DoPE.ERR Pos(DoPE.CTRL MoveCtrl, double Speed, double Destination, ref short Tan);
DoPE.ERR is also an type enum. However, I cannot reach the definition of a function named "Pos". Coud it be within the .dll included ?
The following is the code that allows me to access the position of the piston (without the global variables):
private int OnData(ref DoPE.OnData Data, object Parameter)
{
if (Data.DoPError == DoPE.ERR.NOERROR)
{
DoPE.Data Sample = Data.Data;
Int32 Time = Environment.TickCount;
if ((Time - LastTime) >= 300 /*ms*/)
{
LastTime = Time;
string text;
text = String.Format("{0}", Sample.Time.ToString("0.000"));
guiTime.Text = text;
text = String.Format("{0}", Sample.Sensor[(int)DoPE.SENSOR.SENSOR_S].ToString("0.000"));
guiPosition.Text = text;
text = String.Format("{0}", Sample.Sensor[(int)DoPE.SENSOR.SENSOR_F].ToString("0.000"));
guiLoad.Text = text;
text = String.Format("{0}", Sample.Sensor[(int)DoPE.SENSOR.SENSOR_E].ToString("0.000"));
guiExtension.Text = text;
}
}
return 0;
}
Which is called using
MyEdc.Eh.OnDataHdlr += new DoPE.OnDataHdlr(OnData);
I realise how little I know on how the soft operates, and how frustrating this is for you. If you think this is a lost cause, no problem, I'll try Timothy Jannace solution, and if it does not help me, I'll stick with the MessageBox solution. I just wanted to know why the MessageBox allowed me to sort of achieve my objectif, but the while loop did not, and how to use it in my advantage here.
I tried to use a while loop to compare the current position of the
piston with the goal destination, however, upon entering the while
loop, the variable storing the piston position does not update
anymore.
While you are in the while loop, your app can no longer receive and process the feedback event.
One possible solution would be to use async/await like this:
private const int fullSpeed = 1;
private const int reducedSpeed = 2;
private int currentPistonPositon = 0; // global var updated by event as you described
private async void button1_Click(object sender, EventArgs e)
{
int B = 50;
int C = 75;
pos(fullSpeed, B);
await Task.Run(() =>
{ // pick one below?
// assumes that "B" and "currentPistonPosition" can actually be EXACTLY the same value
while (currentPistonPositon != B)
{
System.Threading.Thread.Sleep(25);
}
// if this isn't the case, then perhaps when it reaches a certain threshold distance?
while (Math.Abs(currentPistonPositon - B) > 0.10)
{
System.Threading.Thread.Sleep(25);
}
});
pos(reducedSpeed, C);
}
Note the button1_Click method signature has been marked with async. The code will wait for the while loop inside the task to complete while still processing event messages because of the await. Only then will it move on to the second pos() call.
Thank you for your answer ! It works like a charm ! (good catch on the
EXACT value). I learnt a lot, and I am sure the async/await combo is
going to be very usefull in the future ! – MaximeS
If that worked well, then you might want to consider refactoring the code and making your own "goto position" method like this:
private void button1_Click(object sender, EventArgs e)
{
int B = 50;
int C = 75;
GotoPosition(fullSpeed, B);
GotoPosition(reducedSpeed, C);
}
private async void GotoPosition(int speed, int position)
{
pos(speed, position);
await Task.Run(() =>
{
while (Math.Abs(currentPistonPositon - position) > 0.10)
{
System.Threading.Thread.Sleep(25);
}
});
}
Readability would be greatly improved.
You could even get fancier and introduce a timeout concept into the while loop. Now your code could do something like below:
private void button1_Click(object sender, EventArgs e)
{
int B = 50;
int C = 75;
if (GotoPosition(fullSpeed, B, TimeSpan.FromMilliseconds(750)).Result)
{
if (GotoPosition(reducedSpeed, C, TimeSpan.FromMilliseconds(1500)).Result)
{
// ... we successfully went to B at fullSpeed, then to C at reducedSpeed ...
}
else
{
MessageBox.Show("Piston Timed Out");
}
}
else
{
MessageBox.Show("Piston Timed Out");
}
}
private async Task<bool> GotoPosition(int speed, int position, TimeSpan timeOut)
{
pos(speed, position); // call the async API
// wait for the position to be reached, or the timeout to occur
bool success = true; // assume we have succeeded until proven otherwise
DateTime dt = DateTime.Now.Add(timeOut); // set our timeout DateTime in the future
await Task.Run(() =>
{
System.Threading.Thread.Sleep(50); // give the piston a chance to update maybe once before checking?
while (Math.Abs(currentPistonPositon - position) > 0.10) // see if the piston has reached our target position
{
if (DateTime.Now > dt) // did we move past our timeout DateTime?
{
success = false;
break;
}
System.Threading.Thread.Sleep(25); // very small sleep to reduce CPU usage
}
});
return success;
}
If you're using events you are probably having concurrency issues. Especially with events being raised every 30ms!
A very simple way to handle concurrency is to use a lock object to prevent different threads from using contested resources simultaneously:
class MyEventHandler
{
private object _lockObject;
MyEventHandler()
{
_lockObject = new object();
}
public int MyContestedResource { get; }
public void HandleEvent( object sender, MyEvent event )
{
lock ( _lockObject )
{
// do stuff with event here
MyContestedResource++;
}
}
}
Keep in mind that is very simple and by no means perfect in every scenario. If you provide more information about how the events are raised and what you're doing with them people will be able to provide more help.
EDIT:
Using that signature you posted for the Pos method I was able to find documentation on the library you are using: https://www.academia.edu/24938060/Do_PE
The reason you only see the method signature when you goto definition is because the library has been compiled into a dll. Actually, it probably wouldn't be that useful to see the code anyway because it looks like the library is a C# wrapper around native (c or c++) code.
Anyways, I hope the documentation is helpful to you. If you look at page 20 there are some pointers on doing movement. This is going to be a challenge for a new programmer but you can do it. I would suggest you avoid using the event handler to drive your logic and instead stick with using the synchronous versions of commands. Using the synchronous commands your code should operate the same way it reads.
I believe what you'll want to do is add a call to:
Application.DoEvents();
This will allow your application to process posted messages (events), which will allow that global variable to be updated.
I just wanted to know why the MessageBox allowed me to sort of achieve my objectif, but the while loop did not, and how to use it in my advantage here.
The reason that works is because you're giving the WndProc a chance to process events which have been sent to the application. It's not an intended feature of that call to MessageBox.Show();, but it is a consequence. You can do the same thing with a call to Application.DoEvents(); without the interruption of the message box.
I'm trying to create an UWP app that measure's the time a person has gazed at multiple objects. There are around 300 objects and they all need to measure the time and display that in a text file. I've succesfully coded this for just one object, but I do not know how I am able to do this with multiple ones. I saw this post How to create 300 stopwatches in C# more efficiently? and the answer to that helped me quite a lot, but the code does not implement well with my code. So I like the idea of creating a list of objects and then when the person has gazed in object [o] then the corresponding stopwatch will start when the eyes have entered the object, and stop when the eyes have left the object. Problem is as I mentioned already, the solution does not work well with the code I am working with. This is the code that I used that works for just one element.
public sealed partial class BlankPage1 : Page
{
private GazeElement gazeButtonControl;
private GazePointer gazePointer;
public BlankPage1()
{
this.InitializeComponent();
Stopwatch Timer = new Stopwatch();
gazePointer = GazeInput.GetGazePointer(null);
gazeButtonControl = GazeInput.GetGazeElement(GazeBlock);
gazeButtonControl = new GazeElement();
GazeInput.SetGazeElement(GazeBlock, gazeButtonControl);
gazeButtonControl.StateChanged += GazeButtonControl_StateChanged;
void GazeButtonControl_StateChanged(object sender, StateChangedEventArgs ea)
{
if (ea.PointerState == PointerState.Enter)
{
Timer.Start();
}
if (ea.PointerState == PointerState.Exit)
{
Timer.Stop();
CreateStatistics();
}
}
void CreateStatistics()
{
File.WriteAllText(#"C:\Users\Vincent Korpelshoek\AppData\Local\Packages\app.a264e06e2-5084-4424-80a9-bee5f5fbb6b6_8wekyb3d8bbwe\LocalState\Resultaten.txt", Timer.Elapsed.ToString(););
}
}
}
The "GazeBlock" is the name of the first object that has been created in the XAML file. So long story short, I'd like to implement this solution:
static Dictionary<object, Stopwatch> stopwatchesByObject;
static void Main(string[] args)
{
List<object> objects = new List<object>();
// now you have to fill the objects list...
stopwatchesByObject = new Dictionary<object, Stopwatch>();
foreach (var o in objects)
{
stopwatchesByObject.Add(o, new Stopwatch());
}
}
// Call this method when the user starts gazing at object o
static void StartGazingAt(object o)
{
stopwatchesByObject[o].Start();
}
// Call this method when the user stops gazing at object o
static void StopGazingAt(object o)
{
stopwatchesByObject[o].Stop();
}
static void CreateStatistics()
{
StringBuilder sb = new StringBuilder();
foreach (var entry in stopwatchesByObject)
{
sb.AppendLine($"Gazed at {entry.Key.ToString()} for {entry.Value.Elapsed.TotalSeconds} seconds.");
}
File.WriteAllText("c:\\temp\\statictics.txt", sb.ToString());
}
But I do not know how to 'merge' these two together so the solution not only works for just one object, but for around 300 of them. If anyone knows how to help me to make this work, thank you!
Vincent
It seems that for each object you create, you need to add it to the dictionary (along with a new Stopwatch), then add the GazeButtonControl_StateChanged event handler to it (you could add this same event handler to all of the controls), then in that event handler you would reference the correct stopwatch by using the sender argument: stopwatchesByObject[sender].Start();
This may not be exactly correct, but here's what I think you'd need to do to merge the two pieces of code:
public sealed partial class BlankPage1 : Page
{
private GazeElement gazeButtonControl;
private GazePointer gazePointer;
static Dictionary<object, Stopwatch> stopwatchesByObject;
public BlankPage1()
{
this.InitializeComponent();
gazePointer = GazeInput.GetGazePointer(null);
gazeButtonControl = GazeInput.GetGazeElement(GazeBlock);
gazeButtonControl = new GazeElement();
GazeInput.SetGazeElement(GazeBlock, gazeButtonControl);
gazeButtonControl.StateChanged += GazeButtonControl_StateChanged;
// Add the object to our dictionary along with a new stopwatch
stopwatchesByObject.Add(gazeButtonControl, new Stopwatch());
private void GazeButtonControl_StateChanged(object sender, StateChangedEventArgs ea)
{
// Use the sender argument to choose the correct timer
if (ea.PointerState == PointerState.Enter)
{
if (stopwatchesByObject.ContainsKey(sender))
{
stopwatchesByObject[sender].Start();
}
}
else if (ea.PointerState == PointerState.Exit)
{
if (stopwatchesByObject.ContainsKey(sender))
{
stopwatchesByObject[sender].Stop();
CreateStatistics();
}
}
}
private void CreateStatistics()
{
StringBuilder sb = new StringBuilder();
foreach (var entry in stopwatchesByObject)
{
sb.AppendLine($"Gazed at {entry.Key} for {entry.Value.Elapsed.TotalSeconds} seconds.");
}
File.WriteAllText("c:\\temp\\statictics.txt", sb.ToString());
}
}
}
#Vincent perhaps it would be worth looking at this in a different way.
With eye tracking the user can only look at one location on the screen at any point in time, so unless your objects are layered overtop of each other in 2D space or potentially aligned in the line of sight in 3D space, you may only be interested in timing the length of time the users gaze point stays in the current topmost object. One stopwatche might be sufficient to keep track of the time from OnEnter to OnExit for the active object.
If on the OnExit you add the duration of time for that particular gaze interaction to lastGazedObject's cumulative time count, you probably do not need to (or want to) manage 300 stopwatches and can likely just reuse the same stopwatch each time the user's gaze enters an object then leaves the object. As it leaves one object the very next gaze point will either fall on another object or on empty space with no object.
Have you taken a look at this sample ?
It has many of the pieces for determining how long the gaze remains in a single object, with some additional logic to track the lastGazedObject you might be able to accomplish what you are after without managing a whole bunch of stopwatches or timers.
However, even if the scenario that you are trying to solve for does approach the problem like a ray cast that could be intersecting more than one object at a time (due to overlay or alignment in space) it should still be easy to have one long running stop watch and just keep track of a flag property for each object of UserIsGazingAt along with when the GazeAtStarted, then calculate the duration as soon as the gaze moves away from the object and add the duration to the objects total duration.
HTH
I'm working on a plugin application. I have a frmDatasheet.cs (backend) and it's DatasheetPlugin.cs (frontend). I am working on a broadcast event between this datasheet and a model plugin, so that if someone goes back to the datasheet, makes some changes, and then goes back to modeling, modeling will be know of the new state and update itself.
The problem I'm having is the call to Broadcast is in the frmDatasheet, which goes to the datasheetPlugin to Raise the Broadcast Request, and I'm getting nulls because I'm leaving the plugin then coming back to it and everything is lost in that back and forth. Here's my code:
//in the frmDatasheet.cs, click GoToModeling, this is last few lines
IDictionary<string, object> packedState = new Dictionary<string, object>();
packedState = PackState(); <----packs up state to send
frmState.Broadcast(packedState); <----- had to instantiate new Plugin to get at .Broadcast
at the top of frmDataSheet.cs
private DatasheetPlugIn frmState = new DatasheetPlugIn();
Is this possibly the problem?? getting new DatasheetPlugin..does that clear it out, but how else can I get at the .Broadcast?
Here's my code in the DatasheetPlugin.cs
public void Broadcast(IDictionary<string,object> packedState)
{
signaller.RaiseBroadcastRequest(packedState);
}
I don't get an error, but the signaller shows the events (BroadcastState, ProjectOpened, ProjectSaved), but they have all null values. Then it goes to the signaller, checks to see if BroadcastState has any subscribers, fails because signaller is null.
How do I ensure that when I get back to the Plugin from the frmDatasheet, everything is still intact? If I put the call to .Broadcast locally in the plugin on some click event, the signaller is not null. So, I'm pretty sure its due to the back and forth and not preserving information.
Update: I should probably include code related to the signaller. Each plugin has:
private VBTools.Signaller signaller; //declared at top of plugin
//This function imports the signaller from the VBProjectManager
//Happens when app loads for each plugin.
[System.ComponentModel.Composition.Import("Signalling.GetSignaller", AllowDefault = true)]
public Func<VBTools.Signaller> GetSignaller
{
get;
set;
}
public void OnImportsSatisfied()
{
//If we've successfully imported a Signaller, then connect its events to our handlers.
signaller = GetSignaller();
signaller.BroadcastState += new VBTools.Signaller.BroadCastEventHandler<VBTools.BroadCastEventArgs>(BroadcastStateListener);
signaller.ProjectSaved += new VBTools.Signaller.SerializationEventHandler<VBTools.SerializationEventArgs>(ProjectSavedListener);
signaller.ProjectOpened += new VBTools.Signaller.SerializationEventHandler<VBTools.SerializationEventArgs>(ProjectOpenedListener);
this.MessageSent += new MessageHandler<VBTools.MessageArgs>(signaller.HandleMessage);
}
Thanks for any insight!!
When you instantiate a new DatasheetPlugin class that has this line:
private VBTools.Signaller signaller; //declared at top of plugin
The "signaller" object will be null until you instantiate it, which appears you do so when calling OnImportsSatisfied(). So when you say that you are calling...
private DatasheetPlugIn frmState = new DatasheetPlugIn();
...at the top of the file, if you never call "OnImportsSatisfied()" the signaller will be null.
It may be that you are getting confused between class member variables and static variables. http://msdn.microsoft.com/en-us/library/79b3xss3(v=vs.80).aspx
To solve this problem, I put the GoToModeling click event in the DSPlugin (was in frmDSheet).
void btnGoToModeling_Click(object sender, EventArgs e)
{
IDictionary<string, object> packedState = new Dictionary<string, object>();
packedState = _frmDatasheet.PackState();
Broadcast(packedState);
}
Then the packedState is populated with the current state of the datasheet to be sent to the Broadcast() which is in the same DSPlugin, so I don't lose anything going back and forth between the 2 classes. I took what I needed from the GoToModeling click method in the frmDSheet and moved it up to the PackState so that I can grab that too before broadcasting.
I used pole display(E POS) in my POS c# application.I have two major problem in that,
1. I can't clear the display perfectly.
2. I can't set the cursor position.
I used some dirty tricks to do these.But I am not satisfied with that code.The following code i used.
Code :-
class PoleDisplay : SerialPort
{
private SerialPort srPort = null;
public PoleDisplay()
{
try
{
srPort = new SerialPort("COM1", 9600, Parity.None, 8, StopBits.One);
if (!srPort.IsOpen) srPort.Open();
}
catch { }
}
~PoleDisplay()
{
srPort.Close();
}
//To clear Display.....
public void ClearDisplay()
{
srPort.Write(" ");
srPort.WriteLine(" ");
}
//Display Function
//'line' 1 for First line and 0 For second line
public void Display(string textToDisplay, int line)
{
if (line == 0)
srPort.Write(textToDisplay);
else
srPort.WriteLine(textToDisplay);
}
}
Your problem is that you are calling Write to clear line 1, and WriteLine to clear line 2.
This doesn't make any sense. The only difference between the methods is that WriteLine adds a linebreak to the end. All you are really doing is this outputting this string:
" "\r\n
Without knowing the brand of the pole display you are using, I can't tell you the proper way to do it, but the way you are trying to do it will never work. Most terminals accept special character codes to move the cursor, or clear the display. Have you found a reference for the terminal you are working with? Most displays will clear if you send them CHR(12).
All that aside, there is a major problem with your class design. You should never rely on destructors to free resources in C#.
In C#, the destructor will be called when the garbage collector collects the object, so there is no deterministic way to know when the resource (in this case a Com port), will be collected and closed.
Instead, implement the interface IDisposable on your class.
This requires you to add a Dispose method to your class. This would serve the same purpose as your current destructor.
By doing that, you can utilize a built in language feature in C# to release your resources when the object goes out of scope.
using (PoleDisplay p = new PoleDisplay())
{
// Do Stuff with p
}
// When the focus has left the using block, Dispose() will be called on p.
Send hex code 0C to clear the screen, it works for most displays
here is a code sample:
byte[] bytesToSend = new byte[1] { 0x0C }; // send hex code 0C to clear screen
srPort.Write(bytesToSend, 0, 1);