Reputation: 1
I have this WPF application. The start button starts a dispatcher timer to perform several sequential tasks. Each task can be time consuming. What I want is to manually stop the dispatcher timer when a current task is taking too long (or actually hangs) In theory, the dispatcher timer ticks every 500 ms and updates the stop button. However, the current task that is being processed locks the dispatcher until the current task completes. And when the current task ends, the stop button is now active and takes effect, but not in real time. Tried different priority levels on the dispatcher timer, with no success. I also tried asynchronous tasks and threads, with no success.
How can I make the stop button have the highest priority to react in the user interface?
// GLOBAL VARIABLES
public bool fullStop = false;
public int numTest = 0;
public bool testActive = false;
public string resultIndividualTest = null;
// MAIN
public MainWindow()
{
InitializeComponent();
}
// UI COMPONENTS (Start and Stop Buttons), AND METHODS
private void BStart_Click(object sender, RoutedEventArgs e)
{
// init counter
InitCounterThread();
// reset global variables
numTest = 0; fullStop = false;
// Init DispatcherTimer every 0.5 second with Priority "Render"
timerTests = new DispatcherTimer(DispatcherPriority.Render); // Render
timerTests.Interval = new TimeSpan(0, 0, 0, 0, 500); //500 ms
timerTests.Tick += new EventHandler(TimerTests_Tick);
timerTests.Start();
}
private void BStop_Click (object sender, RoutedEventArgs e)
{
fullStop = true;
// stop DispatcherTimer
timerTests.Stop();
// stop counter
StopCounter();
}
private CancellationTokenSource ts;
private void TimerTests_Tick(object sender, EventArgs e)
{
// SET FOCUS AND REFRESH STOP BUTTON
BStop.Focus();
BStop.Refresh();
// UPDATE LAYOUT UI
this.UpdateLayout();
if (fullStop == false && testActive == false
&& numTest < MAX && resultIndividualTest == null){
// next test (FROM 1 TO MAX)
numTest++;
// now test will be activated until it finishes …
testActive = true;
ts = new CancellationTokenSource();
CancellationToken ct = ts.Token;
Task.Factory.StartNew( () => this.Dispatcher.Invoke(
() => resultIndividualTest = BTestClick(numTest)), ct);
}
else if (resultIndividualTest != null){
// individual test (task) has finished with result no null
resultIndividualTest = null;
testActive = false;
ts.Cancel();
}
else if (numTest >= MAX || fullStop == true){
// stop DispatcherTimer
timerTests.Stop();
// stop counter
StopCounter();
}
else{
// the timer continues …
}
}
public string BTestClick(int numTest){
/* This method does an individual test */
string result = ""; bool r = false;
If (numTest == 1) {r = routine1();}
If (numTest == 2) {r = routine2();}
… … …
If (r == true) {result = "OK";}
else {result = "ERROR"}
return result;
}
public bool routine1(){
bool result = false;
// ... ... this may take very long (from 5 to 40 seconds)
return result;
}
public bool routine2(){
bool result = false;
// ... ... this may take very long (from 5 to 40 seconds)
return result;
}
Upvotes: 0
Views: 20