Sample my class properties every few seconds - c#

my class start new process (Tshark) and start capturing, from the main form i am checking the class properties in order to update my GUI, sometimes the received packets rate i so high that my GUI stuck so i want the option to check whose properties every 1-2 second.
this is my progress change function who checking my class all the time and in this point i am update my GUi, how can i checking those properties every 2 seconds ?
Tshark tshark = new Tshark();
private void bgWSniffer_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
tshark = e.UserState as Tshark;
lblNumberOfReceivedPackets.Text = tshark._receivesPackets.ToString("#,##0");
lblTrafficRate.Text = (tshark._bitsPerSecond * 0.000001).ToString("0.##") + " Mbit/sec" + " (" + tshark._bitsPerSecond.ToString("#,##0") + " Bits/sec" + ")";
lblPacketsRate.Text = tshark._packetsPerSecond.ToString("#,##0") + " Packets/sec";
lblStatus.Text = tshark._status;
lblFileSize.Text = formatBytes(tshark._myFile.Length);
tshark._myFile.Refresh();
}

Check if 2 seconds has passed since the last check. Here, I'm using a class member to tract that time.
private DateTime _LastCheck = DateTime.MinValue;
private private void bgWSniffer_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
if (_LastCheck.AddSeconds(2) <= DateTime.Now)
{
_LastCheck = DateTime.Now;
// do the UI update.
}
}

Instead of updating the UI within the BackgroundWorker you can just create a Timer to do the job
private void bgWSniffer_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
tshark = e.UserState as Tshark;
}
In the ctor create the timer:
_timer = new Timer()
_timer.Intrerval = 2000;
_timer.Tick += UpdateUI;
_timer.Start();
You can add some checking in case the values have changed so you don't update the UI needlessly:
private void UpdateUI()
{
var local = _tshark;
if(local != null)
{
lblNumberOfReceivedPackets.Text = local._receivesPackets.ToString("#,##0");
lblTrafficRate.Text = (local._bitsPerSecond * 0.000001).ToString("0.##") + " Mbit/sec" + " (" + local._bitsPerSecond.ToString("#,##0") + " Bits/sec" + ")";
lblPacketsRate.Text = local._packetsPerSecond.ToString("#,##0") + " Packets/sec";
lblStatus.Text = local._status;
lblFileSize.Text = formatBytes(local._myFile.Length);
local._myFile.Refresh();
}
}

Related

Xamarin app shows blank page while looping

I'm making an Android application on Xamarin and I want this code to be looped over and over.
But when it's looping it shows literally nothing
public MainPage()
{
InitializeComponent();
for (int i = 0; i < 100; i++)
{
Thread.Sleep(2000);
string app = "notepad";
HttpClient httpClient = new HttpClient();
var result = httpClient.GetAsync("LINK/ob/ob.php?text=" + app).Result;
var contents = result.Content.ReadAsStringAsync().Result;
string decider = contents.ToString();
if (decider.Length > 7)
{
van.Text = "The " + app + " is ON";
van.TextColor = Xamarin.Forms.Color.Green;
}
else
{
van.Text = "The " + app + " is off";
}
}
}
first, don't do this in the constructor. Doing so guarantees that your page won't display until the code completes
second, instead of doing this in a loop with Thread.Sleep() use a timer instead
Timer timer;
int counter;
protected override void OnAppearing()
{
timer = new Timer(2000);
timer.Elapsed += OnTimerElapsed;
timer.Enabled = true;
}
private void OnTimerElapsed(object sender, ElapsedEventArgs a)
{
counter++;
if (counter > 100) timer.Stop();
// put your http request code here
// only the UI code updates should run on the main thread
MainThread.BeginInvokeOnMainThread(() =>
{
if (decider.Length > 7)
{
van.Text = "The " + app + " is ON";
van.TextColor = Xamarin.Forms.Color.Green;
}
else
{
van.Text = "The " + app + " is off";
}
});
}

Power source connected event UWP

I am working on a UWP application in C#.
We have a requirement to perform an operation whenever device is connected to power source for charging. We need to sense that event and do our tasks which are dependent on it.
So far I have found this which raises event when 1% charging is decreased
but we are interested in device connected to power source event.
I got one example where event is binded when page loads.
Battery.AggregateBattery.ReportUpdated += AggregateBattery_ReportUpdated;
and get the report as below.
private void GetBatteryReport(object sender, RoutedEventArgs e)
{
// Clear UI
BatteryReportPanel.Children.Clear();
if (AggregateButton.IsChecked == true)
{
// Request aggregate battery report
RequestAggregateBatteryReport();
}
else
{
// Request individual battery report
RequestIndividualBatteryReports();
}
// Note request
reportRequested = true;
}
This is not what I require.
Can anyone please guide me how to sense device power source connected event?
PowerManager.PowerSupplyStatus can be Adequate, InAdequate, or NotPresent:
var pss = PowerManager.PowerSupplyStatus;
if (pss.ToString() == "NotPresent")
{
pluggedin = false;
} else {
pluggedin = true;
}
Try this to get the battery status:
private void OnPageLoad(object sender, RoutedEventArgs e)
{
PowerManager.BatteryStatusChanged += OnBatteryStatusChanged;
}
private async void OnBatteryStatusChanged(object sender, object e)
{
var bs = PowerManager.BatteryStatus;
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
var dischargeTime = PowerManager.RemainingDischargeTime;
this.batteryProgress.Value = PowerManager.RemainingChargePercent;
this.batteryProgressPercentage.Text = PowerManager.RemainingChargePercent + " % remaining";
this.batteryStatus.Text = "Battery Level: " + bs;
this.batteryDischargeTime.Text = "Battery Left: " + dischargeTime.Hours + " hours " + dischargeTime.Minutes + " minutes " + dischargeTime.Seconds + " seconds";
});
}

C# Variable won't update

I'm writing a C# Program to display the Temperature of CPU/GPU from my PS3.
There is a connect button. This works really good and it shows me the Temp. from my PS3's CPU/GPU.
Now I've implemented a "refresh" button, which starts a timer for all x Seconds to do this:
public void get_psdata()
{
//Get data from PS3
cputemp = PS3.GetTemperatureCELL();
gputemp = PS3.GetTemperatureRSX();
psversion = PS3.GetFirmwareVersion();
psversiontype = PS3.GetFirmwareType();
//Set data into Var
L_cputemp_show.Text = cputemp;
L_gputemp_show.Text = gputemp;
L_firmware_show.Text = psversion;
L_type_show.Text = psversiontype;
//Update Label
L_cputemp_show.Refresh();
}
So this "get_psdata" works only on the first time, when i press the connect button. (The connect button starts directly the "get_psdate" function, while the refresh button does a bit different, like you can see later...)
Here is the code to run the get_psdata:
//B_connect, Connect Button
private void b_connect_Click(object sender, EventArgs e)
{
//Connect CCAPI to PS3 if Button clicked
PS3.ConnectTarget(psip);
//Check Connection
if (PS3.SUCCESS(PS3.ConnectTarget(psip)))
{
//Show Status
MessageBox.Show("Connected to: " + psip + "!");
this.L_status_show.Text = "Connected!"; L_status_show.ForeColor = System.Drawing.Color.Green;
//Call Function
get_psdata();
}
else
{
//Show Status
MessageBox.Show("Failed to Connect to: " + psip + "!");
this.L_status_show.Text = "Not Connected!"; L_status_show.ForeColor = System.Drawing.Color.Red;
}
}
For testing, I added a Messagebox.Show to the "get_psdata" function to see if it runs all x Seconds... Yes it does and this is my timer:
//Function to set refresh delay
public void refresh_delay()
{
MessageBox.Show("Delay set to " + refresh_int + " Seconds!");
refresh_int = refresh_int * 1000; //Change to Miliseconds
init_timer();
}
//Timer
public Timer timer1;
public void init_timer()
{
timer1 = new Timer();
timer1.Tick += new EventHandler(timer1_Tick);
timer1.Interval = refresh_int; // in miliseconds
timer1.Start();
}
public void timer1_Tick(object sender, EventArgs e)
{
get_psdata();
}
And this is what starts my timer:
//B_set, Set refresh time button
private void B_set_Click(object sender, EventArgs e)
{
//Check refresh Value
refresh_string = TB_refresh.Text;
//Check empty
if (refresh_string != "")
{
//Check minimum
refresh_int = Convert.ToInt32(TB_refresh.Text);
if (refresh_int < 5)
{
DialogResult confirm = MessageBox.Show("This is not the delay you are looking for! \r (I recommend to set it bigger then 5) \r Continue with " + refresh_int + " Seconds?", "Realy dude?", MessageBoxButtons.YesNo);
if (confirm == DialogResult.Yes)
{
//Call Function
refresh_delay();
}
}
else
{
//Call Function
refresh_delay();
}
}
else
{
MessageBox.Show("Please set refresh delay!");
}
}
So I'm sure that the code will run all x Seconds but the label's are only updated when I hit the connect button, but not if I start the counter after connecting with the B_set button.
The Variables from "get_psdata" are not showing the updated value. They just show the result from the first "Get". Why aren't they show the latest result?
If I use your code in a fresh winforms screen, all works well. I did however use the following implementation for get_psdata.
public void get_psdata()
{
var rnd = new Random();
//Set data into Var
L_cputemp_show.Text = rnd.Next().ToString();
L_gputemp_show.Text = rnd.Next().ToString();
L_firmware_show.Text = rnd.Next().ToString();
L_type_show.Text = rnd.Next().ToString();
//Update Label
L_cputemp_show.Refresh();
}
With an interval of 1 second, this gives me new values on screen every second. Could you try this code please?
If this works well, then the problem is with the PS3 object that doesn't refresh its internals perhaps?

No overload when using a BackgroundWorker

I am getting a ContextSwitchDeadlock when I try to add a large amount of graphics to a map. I would love to use the BackgroundWorker Class especially since I have never had the opportunity, but I am not sure how to in this situation.
C#:
private void AttributeSearchButton_Click(object sender, RoutedEventArgs e)
{
BackgroundWorker bw = new BackgroundWorker();
bw.WorkerReportsProgress = true;
bw.WorkerSupportsCancellation = true;
bw.DoWork += new DoWorkEventHandler(RunQuery);
bw.ProgressChanged += new ProgressChangedEventHandler(ProgressChanged);
}
private void RunQuery(object sender, DoWorkEventArgs e)
{
_attributeQueryGraphicsLayer.Graphics.Clear();
QueryTask queryTask = new QueryTask("http://xx.x.x.xxx:6080/arcgis/rest/services/Calvert_City_Test/MapServer/2");
queryTask.ExecuteCompleted += GeneralQueryTask_ExecuteCompleted;
queryTask.Failed += GeneralQueryTask_Failed;
var dirty = DateTime.UtcNow;
Query query = new Query();
query.OutFields.Add("*");
query.ReturnGeometry = true;
query.Where = "CIS_METR LIKE '%" + QueryParametersTextbox.Text + "%' OR COMMENTS LIKE '%" + QueryParametersTextbox.Text + "%'";
query.OutSpatialReference = MyMap.SpatialReference;
queryTask.ExecuteAsync(query);
}
// Draw results when query is complete
private void GeneralQueryTask_ExecuteCompleted(object sender, ESRI.ArcGIS.Client.Tasks.QueryEventArgs args)
{
// Clear previous results
QueryDataGrid.Visibility = Visibility.Visible;
GraphicsLayer graphicsLayer = MyMap.Layers["QueryResults"] as GraphicsLayer;
graphicsLayer.ClearGraphics();
// Check for new results
FeatureSet featureSet = args.FeatureSet;
bool isExceedTransferLimit = args.ExceededTransferLimit;
try
{
if (featureSet.Features.Count > 0 && isExceedTransferLimit == false)
{
// Add results to map
foreach (Graphic resultFeature in featureSet.Features)
{
//resultFeature.Symbol = ResultsFillSymbol;
graphicsLayer.Graphics.Add(resultFeature);
}
}
else
{
MessageBox.Show("No features found");
}
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
}
// Notify when query fails
private void GeneralQueryTask_Failed(object sender, TaskFailedEventArgs args)
{
MessageBox.Show("Query failed: " + args.Error);
}
private void ProgressChanged(object sender, ProgressChangedEventArgs e)
{
this.ProgressTextbox.Content = (e.ProgressPercentage.ToString() + "%");
}
I know that the logic is off in this, but I am clueless on how to fix it. I have referred to http://msdn.microsoft.com/en-us/library/System.ComponentModel.BackgroundWorker(v=vs.95).aspx for help with how to use the class, however the information provided is not for this specific situation.
What I am wanting to do:
When the user clicks the Search button, it will Run the query. This works perfectly. The problem is when it runs the GeneralQueryTask_ExecuteCompleted I get a ContextSwitchDeadlock message if there are a large amount of records. This also leaves the UI unresponsive.
From what I have read I would need to put:
if (worker.CancellationPending == true)
{
e.Cancel = true;
break;
}
where the time consuming task takes place. The problem is that there is no overloaded method for me to be able to do the QueryTask and the BackgroundWorker. Any help would be appreciated. If you need more information, please let me know.

How to create a Loading Window?

Ok, in my app there are times when loading the DataGridView can take a minute or two. What I want to do is show a GIF in a form with no border until it reaches the end of the loading function. However, if I do:
Views.Loading ldw = new Views.Loading();
ldw.Show();
...
ldw.Close();
...it never actually draws it to the screen and I can't see it. If I do ShowDialog(), it shows the window but never gets past that line of code. I have a feeling it's because it's not a background worker or because the focus gets set back to the parent because of processing...I don't know.
My form is a blank form, added a picture box, added a gif to the picture box, and made FormBorderStyle = none. Any and all help is appreciated.
Update: Current (non-working) Code
private void InitializeBackgroundWorker()
{
//Defines the DoWork Event Handler for _backgroundWorker.
_bgWorkerReports.DoWork += new DoWorkEventHandler(bgWorkerReports_DoWork);
//Defines the RunWorkCompleted Event Handler for _backgroundWorker.
_bgWorkerReports.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgWorkerReports_RunWorkerCompleted);
}
private void bgWorkerReports_DoWork(object sender, DoWorkEventArgs e)
{
ldw.Show();
try
{
string strFilter = "";
if (!_strSearchFilter.Equals(""))
{
strFilter += strFilter.Equals("") ? " " + _strSearchFilter : " and " + _strSearchFilter;
}
if (tvFigure.Nodes.Count > 0)
{
if (_strFigureFilter == "ALL")
{
strFilter += " " + Constants.GetColumnName("Figure") + " LIKE '%%' ";
}
else if (!_strFigureFilter.Equals("") && !_strFigureFilter.Equals(tvFigure.TopNode.Name))
{
if (_strSearchFilter.Equals("") || !cbCurrentFigure.Checked)
{
strFilter += strFilter.Equals("") ? " " + Constants.GetColumnName("Figure") + "='" + _strFigureFilter + "'" : " and " + Constants.GetColumnName("Figure") + "='" + _strFigureFilter + "'";
}
}
}
if (!_strIndentureFilter.Equals(""))
{
strFilter += strFilter.Equals("") ? " " + _strIndentureFilter : " and " + _strIndentureFilter;
}
if (!_strReportFilter.Equals(""))
{
strFilter += (!strFilter.Equals("") ? " and" : "") + " part_id in (" + _strReportFilter + ")";
}
if (strFilter.Length > 0)
{
BindingSource bSource = new BindingSource();
bSource.DataSource = _dataController.PopulateDataGrid(_nViewMode, strFilter).Tables[0];
//Set DataSource to bindingSource for DataGridView.
if (_lstValidationResults.Count > 0)
{
dgvParts.DataSource = _lstValidationResults;
foreach (DataGridViewColumn dc in dgvParts.Columns)
{
dc.DataPropertyName = "ErrorMessage";
dc.Visible = true;
dc.SortMode = DataGridViewColumnSortMode.Programmatic;
dc.AutoSizeMode = DataGridViewAutoSizeColumnMode.ColumnHeader;
}
dgvParts.AutoResizeColumns();
return;
}
else if (!string.IsNullOrEmpty(_strFigureFilter))
{
dgvParts.DataSource = bSource;
dgvParts.Columns[0].Visible = false;
dgvParts.Columns["Description"].Resizable = DataGridViewTriState.False;
dgvParts.Columns["Description"].Width = 750;
}
// Automatically resize the visible rows.
foreach (DataGridViewColumn col in dgvParts.Columns)
{
col.SortMode = DataGridViewColumnSortMode.Automatic;
if (col.Name != "Description")
{
dgvParts.AutoResizeColumn(col.Index);
}
}
dgvParts.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.DisplayedCells;
// Hide the ToolTips for all the cells - redisplay if there is a report.
dgvParts.ShowCellToolTips = true;
// Set the dataGridView control's border.
dgvParts.BorderStyle = BorderStyle.Fixed3D;
// Get and set the ipb_number to the label.
string ipb_number = _dataController.IPBNumber;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void bgWorkerReports_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
ldw.Close();
this.Cursor = Cursors.Default; //Throws error (Cross-thread)
FormatCells();
BuildColumnsComboBox();
int nTotalCount = 0;
foreach (ListViewItem lvi in listView1.Items)
{
int nCount = _lstReportRecords.Where(rr => lvi.Text.Contains(rr.Description)).Count();
nTotalCount += nCount;
lvi.Text = (lvi.Text.Contains("(") ? lvi.Text.Substring(0, lvi.Text.IndexOf("(") + 1) : lvi.Text.Trim() + " (") + nCount.ToString() + ")";
}
rbAllReports.Text = (rbAllReports.Text.Contains("(") ? rbAllReports.Text.Substring(0, rbAllReports.Text.IndexOf("(") + 1) : rbAllReports.Text + " (") + nTotalCount.ToString() + ")";
int nTaggedCount = _lstReportRecords.Where(rr => rr.Description.Contains("Tagged")).Count();
rbTaggedRecords.Text = (rbTaggedRecords.Text.Contains("(") ? rbTaggedRecords.Text.Substring(0, rbTaggedRecords.Text.IndexOf("(") + 1) : rbTaggedRecords.Text + " (") + nTaggedCount.ToString() + ")";
}
Ideally you would have two threads: the GUI thread and the working thread (which can be a BackgroundWorker). Create and show the window in the GUI thread. Handle the loading in the BackgroundWorker's DoWork event. When the loading is done you can call Close() on the load window from the RunWorkerCompleted event and dispose of it.
LoadWindow loadWindow = new LoadWindow();
loadWindow.TopMost = true; // make sure it doesn't get created behind other forms
loadWindow.Show();
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += new DoWorkEventHandler(worker_DoWork);
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
worker.RunWorkerAsync();
void worker_DoWork(object sender, DoWorkEventArgs e)
{
// do your loading here
}
void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// set DataGridView datasource here
...
// close loading window
loadWindow.Close();
}
The problem you might have with displaying the window could be from the TopMost property, which must be set to true. You can also try calling BringToFront() on the loading window after you've created and shown it.
Yes, BackgroundWorker is for exactly this type of purpose. A couple things to add:
Do not interact with the UI in the worker_DoWork event as it is running on a background thread. Set e.Result when you're finished, which you can check from the RunWorkerCompleted event - or use a form-level variable.
Let any exceptions fall through in the worker_DoWork event and you will see them in the worker_RunWorkerCompleted event in e.Error.
If you need the ability to cancel your load, set worker.WorkerSupportsCancellation and check the e.Cancel while in your DoWork event, then you can check e.Cancelled in your RunWorkerCompleted event.
You should call .Dispose() on your BackgroundWorker when finished.
You'll have to run the code to fill the grid on another thread. Something like:
// Set the picturebox loading state, resize the form etc.
PictureBox.SetLoadingImage();
// Initialize a new thread
Thread t = new Thread(new ThreadStart(() =>
{
// Fill the gridview here
GridView1.DataSource = FillWithData();
GridView1.DataBind();
// When finished, reset the picturebox on it's own thread
PictureBox.Invoke((MethodInvoker)(()=> PictureBox.ClearLoadingImage() ));
}));
// Run the thread.
t.Start();

Categories

Resources