I have a long running task and I don't want to block the UI, so I got a DispatcherTimer and I use it's tick event to check the task property IsCompleted but this causes some sort of deadlock because my application stops responding
public partial class MainWindow : Window
{
DateTime beginFirstPhase;
DateTime beginSecondPhase;
DispatcherTimer dispatcherTimer = new DispatcherTimer();
IEnumerable<string> collection;
Task firstPhaseTask;
Task secondPhaseTask;
public MainWindow()
{
InitializeComponent();
}
private void button_Click(object sender, RoutedEventArgs e)
{
progressTxtBox.AppendText("Entering button click event handler\n");
beginFirstPhase = DateTime.Now;
dispatcherTimer.Tick += DispatcherTimer_Tick_FirstPhase;
dispatcherTimer.Interval = new TimeSpan(0, 0, 5);
dispatcherTimer.Start();
progressTxtBox.AppendText("Begining First Phase now\n");
firstPhaseTask = Task.Factory.StartNew(() =>
/*this is basically a big linq query over a huge collection of strings
(58 thousand+ strings). the result of such query is stored in the field named
collection, above*/), TaskCreationOptions.PreferFairness);
progressTxtBox.AppendText("Awaiting First Phase completion...\n");
}
private void DispatcherTimer_Tick_FirstPhase(object sender, EventArgs e)
{
TimeSpan span = DateTime.Now - beginFirstPhase;
//not even the line bellow is executed.
statusTextBlock.Text = $"Running: {span.ToString()}";
if (firstPhaseTask.IsCompleted)
{
dispatcherTimer.Stop();
progressTxtBox.AppendText($"First Phase completed in {span.ToString()}\n");
secondPhase();
}
}
private void secondPhase()
{
beginSecondPhase = DateTime.Now;
progressTxtBox.AppendText("Begining Second Phase now\n"));
dispatcherTimer.Tick -= DispatcherTimer_Tick_FirstPhase;
dispatcherTimer.Tick += DispatcherTimer_Tick_SecondPhase;
dispatcherTimer.Interval = new TimeSpan(0, 0, 5);
dispatcherTimer.Start();
int counter = 0;
secondPhaseTask = Task.Factory.StartNew(() =>
{
foreach (string str in collection)
{
Dispatcher.Invoke(() => progressTxtBox.AppendText($"iteration <{counter++}>\n"));
IEnumerable<Tuple<string, string> queryResult; // = another linq query
foreach (var tuple in queryResult)
{
Dispatcher.Invoke(() => outputListView.Items.Add($"{tuple.Item1} {tuple.Item2} {str}"));
}
}
}, TaskCreationOptions.PreferFairness);
}
private void DispatcherTimer_Tick_SecondPhase(object sender, EventArgs e)
{
TimeSpan span = DateTime.Now - beginSecondPhase;
statusTextBlock.Text = $"Running: {span.ToString()}";
if (secondPhaseTask.IsCompleted)
{
dispatcherTimer.Stop();
progressTxtBox.AppendText($"Second Phase completed in {span.ToString()}\n");
progressTxtBox.AppendText("Execution Complete");
}
}
}
What causes this to block? Does Task.IsCompleted blocks the caller's thread??
Isn't it possible to poll a Task like this at all? if not, is there another option?
You want to "close" over the Task.Run, by using await operator. That way you get to tell user "Awaiting..." then when task completes you are on Gui thread automatically. If you want progress reports I think this is done via the Progress class but can't remember. Anyway this should get you close...
private async void button_Click(object sender, RoutedEventArgs e)
{
progressTxtBox.AppendText("Entering button click event handler\n");
beginFirstPhase = DateTime.Now;
dispatcherTimer.Tick += DispatcherTimer_Tick_FirstPhase;
dispatcherTimer.Interval = new TimeSpan(0, 0, 5);
dispatcherTimer.Start();
progressTxtBox.AppendText("Begining First Phase now\n");
progressTxtBox.AppendText("Awaiting First Phase completion...\n");
firstPhaseTask =await Task.Factory.StartNew(() =>
/*this is basically a big linq query over a huge collection of strings
(58 thousand+ strings). the result of such query is stored in the field named
collection, above*/), TaskCreationOptions.PreferFairness);
progressTxtBox.AppendText("First Phase complete...\n");
}
I'd also suggest changing the results to be...
var results =await Task<IEnumerable<OfType>>.Factory.StartNew(() =>{
return context.where(p=>p.field = fieldvalue);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With