Here is my dilemma:
public void checkCountProgress(int countProgress, int totalDataSize){ //work done here}
public void func1(int passVar)
{
for(int = 0; i<= 2000; i+=64){
//do work
checkCountProgress(i, 2000);
}
}
Everytime when I iterate through the for-loop, i obviously changes by increments of 64. The checkCountProgressFunction gives me the value of i at whichever point my client connection to the remote host gets disconnected. So I want to continue writing and sending data to the network from where I left off. I would manually stop my server, change the value of i in the parameter of the calling function, run, update service reference from client side and continue but now I need to automate that because I now have to include multiple connections to the host. When I look at some examples, it usually refers to passing a parameter from one function, getting its value and using it in another method (How to pass value from one method to another? ) which is entirely different to what I want to do. How can I achieve this?
You mean using settings to store the value at which the loop was stopped?
If so, here's an example of how to use them
In your project's Properties, in the Settings tab add a new setting of you desired value type and set the scope to User. For my example I created one named ValueToResume of type Int and initial value of 0.
static void Main(string[] args)
{
int initialLoopValue = Properties.Settings.Default.ValueToResume;
for (int i = initialLoopValue; i <= 2000; i += 64)
{
//do work
checkCountProgress(i, 2000);
}
Properties.Settings.Default.Reset(); //Loop was completed, we can reset the setting to 0
}
public static void checkCountProgress(int countProgress, int totalDataSize)
{
if (countProgress > 600)
{
Properties.Settings.Default.ValueToResume = countProgress;
Properties.Settings.Default.Save();
Environment.Exit(0); //force application exit
}
}
}
On the second run, the loop will be initialized at value 640
Related
I am building a turn based game with Unity and Netcode.
My connections work and I receive expected behavior on the NetworkManager.
Except for one thing...
I have a server variable, that should be aligned on all clients. It's the index of the player (turn) in the game (CurrentPlayerIndex). The turn should change after a action has been done, but for testing I just made it a button action, so that all clients can change turn (change the CurrentPlayerIndex).
I made it work, so that CurrentPlayerIndex changes correctly on all clients, when one client change the CurrentPlayerIndex. It works so that the variable in a visual label updates with the same variable on all clients.
The problem is that the variable doesn't get stored on the client, so when I increase the CurrentPlayerIndex on one client, it shows the correctly increased CurrentPlayerIndex in the label BUT when I increase the same (already increased) variable on the same client, it just starts from the local index instead.
Let me explain...
I have two clients. Client1 and Client2. CurrentPlayerIndex starts on 0. When I click "increase" three times on Client1, CurrentPlayerIndex increases to 3. This is displayed on both Client1 and Client2. But when I click "increase" 2 times on Client2, the CurrentPlayerIndex starts from 0 again and increases to 3. When I click "increase" on Client1 again, the CurrentPlayerIndex increases to 4 and so on...
I expect that I misunderstand something about the local client and server behavior, but in this case I just want a "global" variable, that can be affected by all clients and aligned on all clients.
Here's the code snippet:
[SerializeField]
public NetworkVariable<int> CurrentPlayerIndex = new NetworkVariable<int>();
public override void OnNetworkSpawn() {
CurrentPlayerIndex.OnValueChanged += OnCurrentPlayerIndexChanged;
}
public override void OnNetworkDespawn() {
CurrentPlayerIndex.OnValueChanged -= OnCurrentPlayerIndexChanged;
}
public void OnCurrentPlayerIndexChanged(int previous, int current) {
UIManager.Instance.gameMenuLabel.text = "Player " + CurrentPlayerIndex.Value + "'s turn";
}
[ServerRpc(RequireOwnership = false)]
public void ChangeTurnServerRpc(int nextPlayerIndex) {
CurrentPlayerIndex.Value = nextPlayerIndex;
}
public void ChangeTurn() {
int nextPlayerIndex = 0;
if (CurrentPlayerIndex.Value+1 < 5) {
nextPlayerIndex = CurrentPlayerIndex.Value+1;
}
ChangeTurnServerRpc(nextPlayerIndex);
}
I made a SUDOKU solver. When is solve a number it should be written to the screen but it's happen only when the solver is done. Why only then the screen is refreshing when it is done?
ii is the number, jj is the row, ll is the column
private void MainForm_Load(object sender, EventArgs e)
{
...
Thread tr2 = new Thread(adatbszal);
tr2.Start();
}
private void adatbszal()
{
while (fut)
{
Thread.Sleep(10);
if (adat[jj, ll] != 0)
{
SetText(jj, ll, adat[jj, ll].ToString());
}
else
{
SetText(jj, ll, "");
}
}
}
private void SetText(int i, int j, string adat2)
{
if (adatB[i,j].InvokeRequired)
{
valami d = new valami(SetText);
Invoke(d, new object[] { i, j, adat2 });
}
else
{
adatB[i, j].Text = adat2;
}
}
...
Thread th = new Thread(solver);
th.Start();
full project: https://drive.google.com/file/d/1sZTA4Ledfwl3romBY2UTvUoU9MZfY35g/view?usp=sharing
I would suggest putting a breakpoint on Invoke(d, new object[] { i, j, adat2 }); to verify that it is being reached, and when it is, add a breakpoint to if (adatB[i,j].InvokeRequired) before stepping, then make sure that the same parameters are being received to verify that the Invoke is triggering SetText as expected. (Step Into would be simpler, but I'm not sure that would work on an Invoke Line.)
If all that is working, then check if the display updates then adatB[i, j].Text = adat2; executes in the debugger.
I think your code is updating the display like you want it to, but it's not working properly in other regards. In one of my tests, it is just setting the first cell to "2" over and over again, so you won't see any change. You need to verify that the code is doing the right work before you verify that the display is updating properly. I think you may see many problems from having 3 threads running simultaneously which can all update or read the same global values when other threads are assuming these values (like jj) are not changing between lines. I would suggest not sharing data between threads if you are not very experienced with multi-threaded programming. Perhaps you can re-implement this as a single-threaded program that calls an update function periodically instead.
I am taking over a C# code from someone who implemented a desktop application to read real time data from the Serial Port and displaying it in charts (using the Chart Class).
The code seems to be working, but is very slow. It seems to be updating the chart around once in 4 seconds (0.25Hz). However, I can see that it is multi-threaded and has no delay commands, so I don't understand why it is running so slow. Could the updating of charts slow it down? Ideally I would like to achieve 1000 data points per second (1kHz), displaying it in real time and saving it to the hard disk, where the size of each data point is about 30 bytes.
I spent few days understanding the code, but it's too cumbersome to follow, all written in a single file, with no comments. Is my goal of reading 1000 data points per second realistic/achievable?
I'm also considering to re-write the code (as opposed to trying to fix it), considering it's only about 2,500 lines long. Any tips would be appreciated. Also, if I rewrite the code, what language might be better for this application?
I developed some code where I got significant performance improvement, it may work for you. Here is what I did-
Step 1: I would first identify, which one is the bottle neck, drawing/rendering of the chart
or serial port
Step 2: If you find its the rendering-- then add this in your form/chart setup, it will draw much faster. But first double check to make sure you're not in remote desktop mode.
<!-- language: c# -->
// No double buffering for remote, only local
public bool OptimizeOfLocalFormsOnly(System.Windows.Forms.Control chartControlForm)
{
if (!System.Windows.Forms.SystemInformation.TerminalServerSession)
{
SetUpDoubleBuffer(chartControlForm);
return true;
}
return false;
}
public static void SetUpDoubleBuffer(System.Windows.Forms.Control chartControlForm)
{
System.Reflection.PropertyInfo formProp =
typeof(System.Windows.Forms.Control).GetProperty("DoubleBuffered", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
formProp.SetValue(chartControlForm, true, null);
}
I assume you using winform application :
Use serialPort component :
Configure its properties : (BaudRate, DataBits, StopBits, Parity ...)
Make use of its event (DataReceived) to collect your inputs.
You can send commands in a loop and collect the inputs/drawing them on chart component roughly like :
while(/*some condition*/)
{
serialPort.Write(/* your command */);
// you have to think of response time
// so implement something that waits a bit before calling the port again
// I would do it using timers
int tick= Environment.TickCount;
while(Environment.TickCount - tick <= 100) // wait 100 milliseconds
{
Application.DoEvents();
}
}
// collect the data as:
private void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
// use according to your needs, for example
string data = "";
int readByte;
int available;
available = serialPort.BytesToRead;
if(available >= 30) // 30 bytes as stated in your question
{
for(int i=0; i<30; i++)
{
readByte = serialPort.ReadByte();
data += String.Format("{0:2X}", readByte);
}
// you can call some methods to save/display your collected data from here
save_to_file(data);
display_to_chart(data);
}
}
I developed a similar app where I was displaying 16charts * 256 samples/sec. Storing the data in a buffer and creating a separate thread for updating the charts worked for me.
When new data is read, data is stored in a list or array. Since it is real-time data, the timestamps are also generated here. Using the sample rate of the data acquired: timeStamp = timeStamp + sampleIdx/sampleRate;
public void OnDataRead(object source, EEGEventArgs e)
{
if ((e.rawData.Length > 0) && (!_shouldStop))
{
lock (_bufferRawData)
{
for (int sampleIdx = 0; sampleIdx < e.rawData.Length; sampleIdx++)
{
// Append data
_bufferRawData.Add(e.rawData[sampleIdx]);
// Calculate corresponding timestamp
secondsToAdd = (float) sampleIdx/e.sampleRate;
// Append corresponding timestamp
_bufferXValues.Add( e.timeStamp.AddSeconds(secondsToAdd));
}
}
Then, create a thread that sleeps every N ms (100ms is suitable for me for a 2 seconds display of data, but if I wanna display 10 seconds, I need to increase to 500ms of sleep time for the thread)
//Create thread
//define a thread to add values into chart
ThreadStart addDataThreadObj = new ThreadStart(AddDataThreadLoop);
_addDataRunner = new Thread(addDataThreadObj);
addDataDel += new AddDataDelegate(AddData);
//Start thread
_addDataRunner.Start();
And finally, update the charts and make the thread sleep every N ms
private void AddDataThreadLoop()
{
while (!_shouldStop)
{
chChannels[1].Invoke(addDataDel);
// Sleeep thread for 100ms
Thread.Sleep(100);
}
}
The AddData method, simply reads the X (timestamp) and Y values stored in the buffer and add its to the charts using ptSeries.Points.AddXY(xValue, yValue)
As working on multi-threaded application, I have once scenario where I need to assign value to static field. I want to use the latest value of static field in all rest of the threads.
Code is seems like below:
Main() Method:
for (var i = 1; i <= 50; i++)
{
ProcessEmployee processEmployee = new ProcessEmployee();
Thread thread = new Thread(processEmployee.Process);
thread.Start(i);
}
public class ProcessEmployee
{
public void Process(object s)
{
// Sometimes I get value 0 even if the value set to 1 by other thread.
// Want to resolve this issue.
if (StaticContainer.LastValue == 0)
{
Console.WriteLine("Last value is 0");
}
if (Convert.ToInt32(s) == 5)
{
StaticContainer.LastValue = 1;
Console.WriteLine("Last Value is set to 1");
}
// Expectation: want to get last value = 1 in all rest of the threads.
Console.WriteLine(StaticContainer.LastValue);
}
}
public static class StaticContainer
{
private static int lastValue = 0;
public static int LastValue
{
get
{
return lastValue;
}
set
{
lastValue = value;
}
}
}
Question:
Basically, I want to know that once I set specific value to static field by any thread, I want to get the same value (latest value set by another thread) in rest of the threads always.
Please do give me any idea on this.
Thanks in advance!
Basically, I want to know that once I set specific value to static field by any thread, I want to get the same value (latest value set by another thread) in rest of the threads always.
It sounds like you're basically missing a memory barrier. You could work this out with explicit barriers but no locks - or you could just go for the brute-force lock approach, or you could use Interlocked:
private static int lastValue;
public int LastValue
{
// This won't actually change the value - basically if the value *was* 0,
// it gets set to 0 (no change). If the value *wasn't* 0, it doesn't get
// changed either.
get { return Interlocked.CompareExchange(ref lastValue, 0, 0); }
// This will definitely change the value - we ignore the return value, because
// we don't need it.
set { Interlocked.Exchange(ref lastValue, value); }
}
You could use volatile as suggested by newStackExchangeInstance in comments - but I'm never actually sure I fully understand exactly what it means, and I strongly suspect it doesn't mean what most people think it means, or indeed what the MSDN documentation states. You may want to read Joe Duffy's blog post on it (and this one too) for a bit more background.
If two different threads may access the same field/variable and at least one of them will be writing, you need to use some sort of locking. For primitive types use the Interlocked class.
public static class clsCounter
{
static int count;
public static int Counter
{
get { return count; }
set { count = value; }
}
}
The above is the static class that is used to record a number.
Also, I have two projects within a VS2010 solution, one of which is a class library. In one of these classes, I have got the following code which uses clsCounter.
if (clsCounter.Counter == 0)
countIES++;
else
countIES = 0;
Now, in the other project, I set some new values to clsCounter
clsCounter.Counter = 50;
However, for some reason, I am not able to set clsCounter.Counter to 50, thus I always get countIES++. The code looks okay to me, and I have no idea what's wrong with it? Can anyone help?
Thanks.
EDIT:
I wonder if it has something to do with the scope of projects within vs solution?
Solution Structure
Solution
ExcelAddIn
Form1.cs => (clsCounter.Counter = 50)
...
ClassLibrary
clsCounter => (static class)
...
EDIT 2:
clsCounter.Counter = 50; is actually running in backgroundworker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) event. Could this be a possible issue?
EDIT 3:
I have uploaded a sample project that seems to be able to reproduce the same problem. Here's the shared link: => http://www.4shared.com/folder/sInyNWyi/_online.html
What I would like to do here is to populate a cell with value, Other case after the button 'set value' is pressed. The static class and UDF can be found in the class library.
Note that, to be able to use =testFunc() within excel addin, need to find it in automation server list and enable it. So just go File->Option->Addin->Under Manage Add-in->Click GO->Automation->Ebale ClassLibrary1.UDF
Please also check if the option "Register for COM interop" has been enabled or not before launching the debugger. To find it, go ClassLibrary1 Property -> Build -> Under Output, check Register for COM interop.
Add the following line to your static property:
public static class clsCounter
{
private static int count;
public static int Counter
{
get {
Debug.WriteLine("Counter viewed");
return count;
}
set {
Debug.WriteLine("Counter Changed from {0} to {1}", count, value);
count = value;
}
}
}
Then you can watch your debugger and set breakpoints on the counter which will allow you to find out which part of the code is modifying your counter inappropriately. A static counter will be initialised "at some time" before it is accessed. I would say you are setting the counter and something somewhere is immediately incrementing it before you read it.
Finally, I think I found a workaround although it had nothing to do with the static. I was kinda inspired by the idea of using cookies in the web apps.
Similarly, all I need to do here is:
store a value in a temporary text file, by doing
System.IO.File.WriteAllText(#"C:\countIESValue.txt", value);
in the "set value" button click event handler.
And read the stored value whenever I need it from the above text file and assign it to a local variable.
if(System.IO.File.Exists(#"C:\countIESValue.txt"))
{
string val = System.IO.File.ReadAllText(#"C:\countIESValue.txt");
}
The text file can also be deleted after done processing. In this way, I don't have to worry about any scope or application domain issues, although the permission of writing files is required. I am glad it worked pretty all right for me.