Threading.Timer crashing my Winform app? - winforms

I'm using a Threading.Timer to execute a task on the hour every hour, but when the timer ticks, the app always crashes when processing the code to execute in the tick. It crashes with no exceptions or warnings, even if I put the whole thin in a try/catch. Very strange. Below is my setup and any help would be appreciated! It seems like crashes when it tries to access the TextBox GrepCmdTextBox, but I thought reading from another thread was okay, just not writing.
Setting up timer:
var timeOfDay = DateTime.Now.TimeOfDay;
var nextHour = TimeSpan.FromHours(Math.Ceiling(timeOfDay.TotalHours));
var delta = (nextHour - timeOfDay).TotalMilliseconds;
System.Threading.Timer NextHourTimer = new System.Threading.Timer(new System.Threading.TimerCallback(NextHourTimer_Tick), null, (long)delta, (long)TimeSpan.FromHours(1).TotalMilliseconds);
Tick event:
private void NextHourTimer_Tick(object sender)
{
// If thread is not null and is busy, cancel and restart
if (MonitoringThread != null)
{
if (MonitoringThread.TailThread.IsBusy)
{
MonitoringThread.TailThread.CancelAsync();
System.Threading.Thread.Sleep(50);
// Get grep command, if specified
string optionalGrep = String.Empty;
if (GrepCmdTextBox.Text.StartsWith("grep") || GrepCmdTextBox.Text.StartsWith("egrep"))
optionalGrep = " | " + GrepCmdTextBox.Text;
MonitoringThread.TailThread.RunWorkerAsync(optionalGrep);
}
}
}

Cancelling the asynchronous process can take time, the background thread will have to 'finalize', returning from DoWork() and waiting for an opportunity to run the RunWorkerCompleted event, if any.
Instead of cancellation, in this case it would be better to cancel then Dispose() the object, creating a new BGW, as they are as 'cheap-as-chips'.
I hope this helps.

Related

Windows Form UI Update issue with Task in C#

We are working on a windows application which caters to an engineering calculation which are essentially very long running. So we are basically trying to keep the calculation module separate and working in a separate worker thread and pass it an Action delegate in method signature which will be invoked to report the calculation progress in the UI. The delegate handler declared in the UI will be updating the UI. We found that while a huge loop is running in the calculation, the UI is not showing the periodic progress and only displaying the final result. If a Thread Sleep for 1 millisecond is introduced in the calculation loop, the UI is getting updated correctly. This is not expected behavior as we are executing the calculation using a separate Task and updating the UI using BeginInvoke calls.
I have created a simple application to demonstrate our approach and code so that it is easier to understand. It is obvious that we are missing something very simple but cannot quite pin it down. Will appreciate any insights.
Thanks for reading.
private void cmdStart_Click(object sender, EventArgs e)
{
txtResultDIsplay.Text = "";
var maxIterations = long.Parse(txtIterationNo.Text.Trim());
var ui = TaskScheduler.FromCurrentSynchronizationContext();
Task<double> calculationTask = Task.Factory.StartNew<double>(
() => SumRootN(maxIterations, UpdateProgress));
var handleResultTask = calculationTask.ContinueWith((t) => DisplayResult(t),
CancellationToken.None, TaskContinuationOptions.OnlyOnRanToCompletion, ui);
}
private void DisplayResult(Task<double> calculationTask)
{
txtResultDIsplay.Text = "Final Calculation Result : " + calculationTask.Result.ToString();
}
private void UpdateProgress(string msg)
{
this.BeginInvoke((MethodInvoker)delegate
{
txtResultDIsplay.Text = msg;
});
}
public double SumRootN(long maxIterations, Action<string> progressUpdateDelegate)
{
int root = 20;
double result = 0;
for (long i = 1; i < maxIterations; i++)
{
Thread.Sleep(1);
result += Math.Exp(Math.Log(i) / root);
progressUpdateDelegate(result.ToString("0.00000"));
}
return result;
}
It is possible you are flooding the UI thread with your progress updates. You need to find a way to prevent lots of updates occurring.
We can solve the problem using tasks!
Task progressTask = null;
private void UpdateProgress(string msg)
{
//only schedule work if the task if not running
if(progressTask == null || progressTask.IsCompleted) //updates will end if there is an exception!
{
//Create a task representing the update
progressTask = Task.Factory.FromAsync<object>(BeginInvoke(new Action(() => txtResultDIsplay.Text = msg)), this.EndInvoke)
.ContinueWith(() => System.Threading.Thread.Sleep(100)); //add a sleep on the end
}
}
Note that locking will not do here as you want to skip the update if there is already an update occurring.

issues with BackGround worker across classes

this is my first question in this forum, hope it will not be duplicated somewhere because i have searched for the respons for almost 4 weeks without making any progress.
here is my situation,
im developing an application that need to do a lot of background operation, for that reason i creat 2 BKW, the first one used to load data from a DB and put it inside an observable collection , 'no need to report progress or support cancelation for this one' :
private Boolean loadTestSteps()
{
// Create a background worker thread that don't report progress and does not
// support cancelation
BackgroundWorker wk_LoadTestSteps = new BackgroundWorker();
wk_LoadTestSteps.DoWork += new DoWorkEventHandler(wk_LoadTestSteps_DoWork);
wk_LoadTestSteps.RunWorkerAsync();
return true;
}
observable collection class :
public class clsTestStep : DependencyObject
{
public static DependencyProperty TestStepProperty = DependencyProperty.Register(
"TestStep", typeof(String), typeof(clsTestStep));
public string TestStep
{
get { return (string)GetValue(TestStepProperty); }
set { SetValue(TestStepProperty, value); }
} and so on for the rest of items....
now the main backGround that should do the longer operation and in the same time report the progress to the main UI ,declared like so
private void InitializeBackGroundWork()
{
_wk_StartTest = new BackgroundWorker();
// Create a background worker thread that ReportsProgress &
// SupportsCancellation
// Hook up the appropriate events.
_wk_StartTest.DoWork += new DoWorkEventHandler(_wk_StartTest_DoWork);
_wk_StartTest.ProgressChanged += new ProgressChangedEventHandler
(_wk_StartTest_ProgressChanged);
_wk_StartTest.RunWorkerCompleted += new RunWorkerCompletedEventHandler
(_wk_StartTest_RunWorkerCompleted);
_wk_StartTest.WorkerReportsProgress = true;
_wk_StartTest.WorkerSupportsCancellation = true;
_wk_StartTest.RunWorkerAsync();
}
in the do work events, exactly in the foreach loop i encontered an error saying : you cannot access this object because another thread own it :
void _wk_StartTest_DoWork(object sender, DoWorkEventArgs e)
{
//Loop through each test step and perform Test
foreach (clsTestStep item in _testStep)
{
Thread.Sleep(200);
temp[0] = item.TestStep;
temp[1] = item.Delay.ToString();
temp[2] = item.NumberRepetition.ToString();
temp[3] = item.Mode.ToString();
//Report % of Progress, Test step Name,and the paragraph from Class PerformTest
_wk_StartTest.ReportProgress(counter,
temp[0]);
counter += 1;
_performTest.Fdispatcher(temp, out _paragraph);
//_si.PgBarMax = Convert.ToDouble(_testStep.Count);
}
//Report completion on operation completed
_wk_StartTest.ReportProgress(counter);
}
what im missing here please, because my head is gonna explod from searching !!!
It sounds like your ObservableCollection is created and so owned by an other thread so your _wk_StartTest_DoWork method can't access it.
Where your _testStep variable comes from ?
By the way, in a multithread environment when many thread access the same data you should prefer the use of ConcurrentBag class instead of an ObservableCollection. ConcurrentBag is thread safe.
for the ones that may enconter this kind of problem ^^
finnaly i have found a way to acess class even if its not owned by the current thread here a nice article explaining step by step how to do this here

How to get Json Array to work inside Asyntask - Android [duplicate]

This question already has an answer here:
How to put Json inside asynctask - Android
(1 answer)
Closed 9 years ago.
I have an Asynctask that uses a Json function in the doInBackground part. The function collects an array of comments and places them into a variable called KEY_COMMENTS. In the onPreExecute it places the comments into a textView using a for loop to select each comment individually. The problem is that its not selecting each comment it will only select one. If I set the loop to go for more than 1 time it will crash the app. Here is my code,
class loadComments extends AsyncTask<JSONObject, String, JSONObject> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
}
protected JSONObject doInBackground(JSONObject... params) {
//do your work here
JSONObject json2 = CollectComments.collectComments(usernameforcomments, offsetNumber);
return json2;
}
#Override
protected void onPostExecute(JSONObject json2) {
try {
if (json2.getString(KEY_SUCCESS) != null) {
registerErrorMsg.setText("");
String res2 = json2.getString(KEY_SUCCESS);
if(Integer.parseInt(res2) == 1){
JSONArray array = json2.getJSONArray(KEY_COMMENT);
for(int i = 0; i < 2; i++) {
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
commentBox.setBackgroundResource(R.drawable.comment_box_bg);
layoutParams.setMargins(0, 10, 0, 10);
commentBox.setPadding(0,0,0,10);
commentBox.setOrientation(LinearLayout.VERTICAL);
linear.addView(commentBox, layoutParams);
commentBoxHeader.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
commentBoxHeader.setBackgroundResource(R.drawable.comment_box_bg);
commentBoxHeader.setBackgroundResource(R.drawable.comment_box_header);
commentBox.addView(commentBoxHeader);
commentView.setText(array.getString(i));
LinearLayout.LayoutParams commentViewParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
commentViewParams.setMargins(20, 10, 20, 20);
commentView.setBackgroundResource(R.drawable.comment_bg);
commentView.setTextColor(getResources().getColor(R.color.black));
commentBox.addView(commentView, commentViewParams);
}
}//end if key is == 1
else{
// Error in registration
registerErrorMsg.setText(json2.getString(KEY_ERROR_MSG));
}//end else
}//end if
} //end try
catch (JSONException e) {
e.printStackTrace();
}//end catch
}
}
doInBackGround : method is used as a Thread !
onPostExecute : acts as a UI Thread !
So try to put your any-long running code in , doInBackGround method !
When an asynchronous task is executed, the task goes through 4 steps:
From the Docs :
onPreExecute(), invoked on the UI thread before the task is executed. This step is normally used to setup the task, for instance by showing a progress bar in the user interface.
doInBackground(Params...), invoked on the background thread immediately after onPreExecute() finishes executing. This step is used to perform background computation that can take a long time. The parameters of the asynchronous task are passed to this step. The result of the computation must be returned by this step and will be passed back to the last step. This step can also use publishProgress(Progress...) to publish one or more units of progress. These values are published on the UI thread, in the onProgressUpdate(Progress...) step.
onProgressUpdate(Progress...), invoked on the UI thread after a call to publishProgress(Progress...). The timing of the execution is undefined. This method is used to display any form of progress in the user interface while the background computation is still executing. For instance, it can be used to animate a progress bar or show logs in a text field.
onPostExecute(Result), invoked on the UI thread after the background computation finishes. The result of the background computation is passed to this step as a parameter.

Threading.Timer stack overflow

Hy, I just wanted to find out how to implement a loop that takes around 80 to 120ms (mostly 80ms) to execute. The loop has to execute for about 30 minutes... basically it is a SURF matching algorithm.
Currently I am using a System.Threading.Timer to create a timer that executes after every 90ms, but the problem is that since the computation time is variable, so after some time the stack overflows and the program closes.
I'm using WPF to create the GUI.
Is there a better way to implement such a loop using threading? Any help would be much appreciated! Thanks in advance.
//initialization
private System.Threading.Timer Visual_AR1;
Visual_AR1 = new System.Threading.Timer(new TimerCallback(Video_AR1), null, 0, 90);
private void Video_AR1(object state)
{
lock (this)
{
// SURF matching
modelImage_AR1 = new Image<Gray, byte>(droneControl_AR1.BitmapImage).Resize(1.8, INTER.CV_INTER_NN);
map_image_d1 = DrawMatches_gpu.GPU_0(wayx, modelImage_AR1, observedImage, pgpuObservedKeyPoints_imp, pgpuObservedDescriptors_imp, out matchTime_0, out pX1, out pY1);
Dispatcher.BeginInvoke((Action)delegate()
{
label4.Content = "Time Taken by GPU_0 : " + matchTime_0.ToString();
});
mask_selector_d1();
}
}
is this a viable solution ?
private Thread threadTask = null;
private void threadTask_Start()
{
if (threadTask == null) {
threadTask = new Thread(SURF);
threadTask.Start();
}
}
private void SURF()
{
while(true)
{
lock (this)
{
// SURF matching
modelImage_AR1 = new Image<Gray, byte>(droneControl_AR1.BitmapImage).Resize(1.8, INTER.CV_INTER_NN);
map_image_d1 = DrawMatches_gpu.GPU_0(wayx, modelImage_AR1, observedImage, pgpuObservedKeyPoints_imp, pgpuObservedDescriptors_imp, out matchTime_0, out pX1, out pY1);
Dispatcher.BeginInvoke((Action)delegate()
{
label4.Content = "Time Taken by GPU_0 : " + matchTime_0.ToString();
});
mask_selector_d1();
}
thread.sleep(40);
}
}
Instead of making the timer tick perform the work, make the timer tick queue up a job and have something else (presumably threads from the thread pool) consume the jobs. You can use a semaphore to throttle the number of jobs running simultaneously and you can examine the state of the queue to avoid this sort of over-commit problem.

WPF, calling server method in background worker

I need in wpf app check messages on server. I have own method which load messages on server-LoadRp().
I would like to create some kind of listener which would check, every 3 seconds whether on the server are not new messages.
I call method for loading messages on dispatcher timer tick event, it is suitable? Any another solution. It’s possible call timer in another thread in wpf?
Code is here:
public MessangerWindow(PokecCommands pokecCmd)
{
InitializeComponent();
PokecCmd = pokecCmd;
_friendsData = PokecCmd.LoadFriends();
friendsListBox.DataContext = _friendsData;
_dispatcherTimer = new DispatcherTimer();
_dispatcherTimer.Tick+=new EventHandler(DispatcherTimer_Tick);
_dispatcherTimer.Interval = new TimeSpan(0,0,3);
_dispatcherTimer.Start();
}
private void DispatcherTimer_Tick(object sender, EventArgs eventArgs)
{
try
{
//try load new message from sever
RP message = PokecCmd.LoadRp();
//arived message
if (message != null)
{
//exist window
if (_chatWindows.ContainsKey(message.Nick))
{
_chatWindows[message.Nick].Show();
}
{
//create new Window
var chatWindow = new ChatWindow(PokecCmd, message);
_chatWindows.Add(message.Nick, chatWindow);
chatWindow.Show();
}
}
}
catch (Exception ex)
{
//MessageBox.Show(ex.Message);
}
}
What is suitable to use:
Dispatcher with no background threads
Dispatcher with background threads
Multiple Threads
If you are ok with locking up your UI for the time it takes to check on the server, using a DispatcherTimer the way you are doing it will work fine.
If checking for new messages could take more than a few milliseconds and you want your UI to be responsive while it checks, you should use multiple threads. In that case, once the new data had arrived you would use Dispatcher.Invoke to display it.
Your code in the thread that checks for messages might look like this:
//try load new message from sever
RP message = PokecCmd.LoadRp();
//arived message
if( message != null )
Dispatcher.Invoke(DispatcherPriority.Send, new Action(() =>
{
//exist window
if (_chatWindows.ContainsKey(message.Nick))
{
_chatWindows[message.Nick].Show();
}
{
//create new Window
var chatWindow = new ChatWindow(PokecCmd, message);
_chatWindows.Add(message.Nick, chatWindow);
chatWindow.Show();
}
}
);

Resources