У меня долгое задание, и я не хочу блокировать пользовательский интерфейс, поэтому у меня есть DispatcherTimer
, и я использую его, чтобы проверить свойство задачи IsCompleted
, но это вызывает какой-то тупик, потому что мое приложение перестает отвечатьМожно ли опросить задачу для завершения?
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");
}
}
}
Что заставляет это блокировать? Does Task.IsCompleted
блокирует поток звонящего? Возможно ли вообще опросить такую задачу? если нет, есть ли другой вариант?
EDIT: Уважаемые оцененные члены сообщества StackOverflow, я получаю несколько ответов, которые в основном говорят: «Не делайте этого так, этот путь лучше». Все это очень хорошо продуманные ответы, и я благодарю всех вас за них. Но мой вопрос заключается в следующем: «Можно ли опросить задачу для завершения и как это сделать». Nevermind это плохой дизайн, потому что это не было частью вопроса. Я понимаю, что могу переписать код для использования ждут и асинхронно, но, поскольку я самообучаюсь, я считаю, что это хорошая идея, чтобы изучить, что может сделать язык.
Это как если бы я задал вопрос о том, как работает goto
, и все ответы, которые я получил, были почему бы не использовать goto
и как его заменить. Я понимаю, что вы все хотите как можно лучше помочь, предоставив мне знания о том, что мой выбор дизайна плох, но, не помогая мне реализовать мой плохой выбор, вы отказываете мне в знаниях о том, как это сделать. И я смиренно верю, что это противоречит духу этого сообщества. Надеюсь, это добавление никого не обидит, у меня нет ничего, кроме уважения ко всем членам сообщества, и я надеюсь, что я сделал это достаточно ясно.
Это не скомпилировано: 'firstPhaseTask = ждет TaskFactor.StartNew (...)'. Кроме того, я второй этап, который начнется только после первой фазы, будет завершен, иначе объекты будут в несогласованном состоянии. Вот почему мне нужно опросить, если первый этап завершен или нет. – FinnTheHuman
Нет, вам не нужно опросить, если вы используете закрытие, оно не скомпилируется, потому что вам нужно изменить код, чтобы он был похож на мое предложение. Если вам нужен результат запроса, верните результаты, как показано в предложении. Когда компилятор попадает в состояние ожидания, этот поток приостанавливается автоматически до возобновления, которое задает результаты var. Тогда вы находитесь в главной теме, и то же самое происходит, когда 2-й ожидание попадает, если у вас есть «Закрытие» ... –