powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / WPF, Silverlight [игнор отключен] [закрыт для гостей] / Отмена задачи вешает UI намертво
19 сообщений из 19, страница 1 из 1
Отмена задачи вешает UI намертво
    #38742605
monstrilla
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Вот такой вот парадокс обнаружил. SleepBeforeInvoke - вешает интерфейс, два остальных метода не вешают, т.е. задача отменяется корректно, попадаем в catch . Кто может объяснить в чем прикол?

Win7, .Net 4.0


Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition></RowDefinition>
        <RowDefinition></RowDefinition>
    </Grid.RowDefinitions>
    <TextBlock Grid.Row="0" 
                Name="_textBlock"
                Text="MainWindow"></TextBlock>
    <Button Grid.Row="1"
            Click="ButtonBase_OnClick"></Button>
</Grid>



Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
public partial class MainWindow : Window
    {
        private readonly CancellationTokenSource _cts = new CancellationTokenSource();
        private Task _task;

        /// <summary>
        /// Вешает приложение намертво на строке _task.Wait();
        /// </summary>
        private void SleepBeforeInvoke()
        {
            for (Int32 count = 0; count < 50; count++)
            {
                if (_cts.Token.IsCancellationRequested)
                    _cts.Token.ThrowIfCancellationRequested();

                Thread.Sleep(500);
                Application.Current.Dispatcher.Invoke(new Action(() => { }));
            }
        }

        /// <summary>
        /// Хорошо работает, попадем в catch
        /// </summary>
        private void SleepAfterInvoke()
        {
            for (Int32 count = 0; count < 50; count++) 
            {
                if (_cts.Token.IsCancellationRequested)
                    _cts.Token.ThrowIfCancellationRequested();
               
                Application.Current.Dispatcher.Invoke(new Action(() => { }));
                Thread.Sleep(500);
            }   
        }

        /// <summary>
        /// Ничего не вешает, тоже хорошо работает
        /// </summary>
        private void BeginInvoke()
        {
            for (Int32 count = 0; count < 50; count++)
            {
                if (_cts.Token.IsCancellationRequested)
                    _cts.Token.ThrowIfCancellationRequested();

                Thread.Sleep(500);
                Application.Current.Dispatcher.BeginInvoke(new Action(() => { }));
            } 
        }

        public MainWindow()
        {
            InitializeComponent();
            _task = Task.Factory.StartNew(BeginInvoke, _cts.Token, TaskCreationOptions.None, TaskScheduler.Default);
        }

        private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
        {
            try
            {
                _cts.Cancel();
                _task.Wait();
            }
            catch (AggregateException)
            {
                
            }
            Debug.WriteLine("Task has been cancelled");
        }
    }
...
Рейтинг: 0 / 0
Отмена задачи вешает UI намертво
    #38743163
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
monstrillaВот такой вот парадокс обнаружил. SleepBeforeInvoke - вешает интерфейсПотому что мёртвая блокировка.

Application.Current.Dispatcher.Invoke ждёт завершения ButtonBase_OnClick
_task.Wait() ждёт завершения SleepBeforeInvoke

Вообще, Dispatcher.Invoke лучше не использовать без особых на то причин. Надо использовать Dispatcher.BeginInvoke.
...
Рейтинг: 0 / 0
Отмена задачи вешает UI намертво
    #38743236
monstrilla
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Алексей К,

но ведь SleepAfterInvoke работает. а разница только в последовательности вызова Thread.Sleep....
...
Рейтинг: 0 / 0
Отмена задачи вешает UI намертво
    #38743245
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
monstrillaАлексей К,

но ведь SleepAfterInvoke работает. а разница только в последовательности вызова Thread.Sleep....Там ещё различия Invoke vs BeginInvoke
...
Рейтинг: 0 / 0
Отмена задачи вешает UI намертво
    #38743260
monstrilla
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Алексей К, нет

SleepBeforeInvoke

авторThread.Sleep(500);
Application.Current.Dispatcher.Invoke(new Action(() => { }));

SleepAfterInvoke

авторApplication.Current.Dispatcher.Invoke(new Action(() => { }));
Thread.Sleep(500);
...
Рейтинг: 0 / 0
Отмена задачи вешает UI намертво
    #38743281
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
monstrillaАлексей К, нет

SleepBeforeInvoke

авторThread.Sleep(500);
Application.Current.Dispatcher.Invoke(new Action(() => { }));

SleepAfterInvoke

авторApplication.Current.Dispatcher.Invoke(new Action(() => { }));
Thread.Sleep(500);
Согласен, перепутал.
...
Рейтинг: 0 / 0
Отмена задачи вешает UI намертво
    #38743300
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Мёртвая блокировка.
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
private void SleepBeforeInvoke()
        {
            for (Int32 count = 0; count < 50; count++)
            {
                if (_cts.Token.IsCancellationRequested)
                    _cts.Token.ThrowIfCancellationRequested();

                Thread.Sleep(500); // <= Тут вызываем отмену и ждём завершения таска.
                Application.Current.Dispatcher.Invoke(new Action(() => { })); // <= Тут ждём завершения buttonClick
            }
        }


Но существует и вероятность того, что SleepAfterInvoke тоже повиснет, если:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
private void SleepAfterInvoke()
        {
            for (Int32 count = 0; count < 50; count++) 
            {
                if (_cts.Token.IsCancellationRequested)
                    _cts.Token.ThrowIfCancellationRequested();
               
                // <= После if и перед началом ожидания в Invoke вызываем отмену и ждём завершения таска.

                Application.Current.Dispatcher.Invoke(new Action(() => { })); // <= Тут ждём завершения buttonClick
                Thread.Sleep(500);
            }   
        }
...
Рейтинг: 0 / 0
Отмена задачи вешает UI намертво
    #38743343
monstrilla
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Алексей К,

я что-то не пойму, разве строка

Код: c#
1.
_cts.Token.ThrowIfCancellationRequested();



не кидает исключение и не инициирует мгновенный возврат из метода?
...
Рейтинг: 0 / 0
Отмена задачи вешает UI намертво
    #38743350
monstrilla
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
и вообще, если поток подвешивает строка

Код: c#
1.
Application.Current.Dispatcher.Invoke(new Action(() => { }));



то почему все работает без Thread.Sleep(500);
...
Рейтинг: 0 / 0
Отмена задачи вешает UI намертво
    #38743351
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
monstrillaАлексей К,

я что-то не пойму, разве строка

Код: c#
1.
_cts.Token.ThrowIfCancellationRequested();



не кидает исключение и не инициирует мгновенный возврат из метода?Отмена обычно выпадает на Thread.Sleep. Между Thread.Sleep и _cts.Token.ThrowIfCancellationRequested находится Dispatcher.Invoke, от которого все беды. :-)
...
Рейтинг: 0 / 0
Отмена задачи вешает UI намертво
    #38743356
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
monstrillaи вообще, если поток подвешивает строка

Код: c#
1.
Application.Current.Dispatcher.Invoke(new Action(() => { }));



то почему все работает без Thread.Sleep(500); Просто везёт пока. Вероятность мёртвой блокировки существует. Я же не зря посоветовал всегда использовать BeginInvoke. :-)
...
Рейтинг: 0 / 0
Отмена задачи вешает UI намертво
    #38743370
monstrilla
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Алексей К, да я так и сделал, просто пытаюсь докопаться до сути. не люблю без понимания делать. честно говоря, понятнее не стало. непонятно кто кого ждет, почему не кидается исключение, почему строка

Код: c#
1.
_cts.Token.ThrowIfCancellationRequested();



вообще не отрабатывает :( если можете подробнее расписать - буду признателен.
...
Рейтинг: 0 / 0
Отмена задачи вешает UI намертво
    #38743400
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
monstrillaАлексей К, да я так и сделал, просто пытаюсь докопаться до сути. не люблю без понимания делать. честно говоря, понятнее не стало. непонятно кто кого ждет, почему не кидается исключение, почему строка

Код: c#
1.
_cts.Token.ThrowIfCancellationRequested();



вообще не отрабатывает :( если можете подробнее расписать - буду признателен.Код в buttonClick ждёт пока завершится таск [_task.Wait()]

и

Таск ждёт пока завершится buttonClick [Dispatcher.Invoke()]
...
Рейтинг: 0 / 0
Отмена задачи вешает UI намертво
    #38743424
monstrilla
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Алексей К,

я, конечно, с одной стороны понимаю, что у меня две операции запускаются синхронно в потоке UI и, по идее это и ведет к блокировке (но при таком сценарии блокировка должна быть стопроцентной, т.е. проявляться всегда , независимо от того, что там еще есть в теле цикла). но тогда возвращаемся к вопросу, почему она не проявляется, если Thread.Sleep() отсутствует или расположен после Invoke() . не понятно, что значит пока везет

*тут смайлик, который головой об стену бьется
...
Рейтинг: 0 / 0
Отмена задачи вешает UI намертво
    #38743426
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
monstrillaпочему она не проявляется, если Thread.Sleep() отсутствует или расположен после Invoke() . не понятно, что значит пока везет Она появляется, но намного реже.
...
Рейтинг: 0 / 0
Отмена задачи вешает UI намертво
    #38743428
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей Кmonstrillaпочему она не проявляется, если Thread.Sleep() отсутствует или расположен после Invoke() . не понятно, что значит пока везет Она появляется, но намного реже.Настолько же реже SleepBeforeInvoke работает без блокировки.
...
Рейтинг: 0 / 0
Отмена задачи вешает UI намертво
    #38743770
monstrilla
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Алексей К,

в этом то и вопрос, какова закономерность. почему блокировка не перманентная, а проявляется как то рандомно. как программить то, если невозможно точно сказать будет код работать или нет
...
Рейтинг: 0 / 0
Отмена задачи вешает UI намертво
    #38743969
monstrilla
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
...
Рейтинг: 0 / 0
Отмена задачи вешает UI намертво
    #38745996
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
monstrillaАлексей К,

в этом то и вопрос, какова закономерность. почему блокировка не перманентная, а проявляется как то рандомно. как программить то, если невозможно точно сказать будет код работать или нетПотому что отмена почти всегда выпадает на Thread.Sleep(500) , по понятным причинам. Поэтому положение Thread.Sleep(500) сильно влияет на ситуацию.
...
Рейтинг: 0 / 0
19 сообщений из 19, страница 1 из 1
Форумы / WPF, Silverlight [игнор отключен] [закрыт для гостей] / Отмена задачи вешает UI намертво
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]