powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / WPF, Silverlight [игнор отключен] [закрыт для гостей] / Задача, запущенная в дочернем окне подвешивает интерфейс
25 сообщений из 46, страница 1 из 2
Задача, запущенная в дочернем окне подвешивает интерфейс
    #38742021
monstrilla
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Есть два окна AuthenticateWindow и MainWindow , разметка и код ниже. Все очень упрощенно, но передает суть и воспроизводит симптомы (желающие могут скопипастить).
Если в конструкторе окна MainWindow юзать тип Thread - все будет работать хорошо, окошко покажется, поток будет работать сам по себе. Если использовать тип Task , то интерфейс подвесится, а именно, окно MainWindow не будет отображаться пока задача не отработает, т.е. пока не пройдет 5 секунд. Собсно вопрос, есть ли возможность использовать класс Task без подвешивания интерфейса? Потому что мне очень нужен механизм отмены задачи и ее свойство Status . Впрочем, если что-то подобное есть у класса Thread - проблема так же решится.

Винда 7, .Нет 4.0.
Важное условие, от TaskScheduler.FromCurrentSynchronizationContext() отказаться не могу.

Код: xml
1.
2.
3.
4.
<Grid>
    <Button Content="OpenMainWindow"
            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.
public partial class AuthWindow : Window
{
    public AuthWindow()
    {
        InitializeComponent();
    }

    private void DoAbsolutelyNothing()
    {

    }

    private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
    {
        Task.Factory.StartNew(DoAbsolutelyNothing).ContinueWith(t =>
        {
            var window = new MainWindow();
            if (window.IsInitialized)
                window.Show();

            Close();
        }, TaskScheduler.FromCurrentSynchronizationContext());
    }
}


MainWindow:

Код: xml
1.
2.
3.
<Grid>
    <TextBlock Text="MainWindow"></TextBlock>
</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.
public partial class MainWindow : Window
{
    private Task _task;

    private void TestMethod()
    {
        Thread.Sleep(5000);
        Debug.WriteLine("TestMethod comleted");
    }

    public MainWindow()
    {
        InitializeComponent();

        // it works badly  
        //_task = Task.Factory.StartNew(TestMethod);

        // it works fine
        new Thread(TestMethod).Start();
    }

    private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
    {

    }
}
...
Рейтинг: 0 / 0
Задача, запущенная в дочернем окне подвешивает интерфейс
    #38742092
капитанская дочка
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
monstrilla,

Код: c#
1.
_task = Task.Run(() => TestMethod());
...
Рейтинг: 0 / 0
Задача, запущенная в дочернем окне подвешивает интерфейс
    #38742113
капитанская дочка
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
monstrilla,

кстати есть такая штукенция

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

Код: c#
1.
_task = Task.Run(() => TestMethod());

Это то же самое.
капитанская дочкаmonstrilla,

кстати есть такая штукенция Эта штука после появления Task больше не нужна. Да и до появления Task она была ни к чему.

капитанская дочкаи еще говорят что эта штука тоже полезнаяЭто тут не причём.
monstrillaВ Task.Factory.StartNew(TestMethod) в данном случае нужно явно указать дефолтный шедулер, запускающий задачу через пул потоков или отдельный поток.

Подробнее: "Синхронизация асинхронных операций с главным потоком приложения" .
...
Рейтинг: 0 / 0
Задача, запущенная в дочернем окне подвешивает интерфейс
    #38742152
капитанская дочка
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей Ккапитанская дочкаmonstrilla,

Код: c#
1.
_task = Task.Run(() => TestMethod());

Это то же самое.

тогда у меня наверное комп особенный раз у меня так работает или может быть потому что It uses the default task scheduler.

Алексей Ккапитанская дочкаmonstrilla,

кстати есть такая штукенция Эта штука после появления Task больше не нужна. Да и до появления Task она была ни к чему.

с этим пожалуй соглашусь хотя и есть некоторые но. ну да ладно

Алексей Ккапитанская дочкаи еще говорят что эта штука тоже полезнаяЭто тут не причём.

что даже parallel.invoke http://ru.wiktionary.org/wiki/%D0%BD%D0%B8_%D0%BF%D1%80%D0%B8_%D1%87%D1%91%D0%BC]нИ при [пробел] чем ? или может быть тс не то что полезно а даже вредно знать о существовании класса parallel?
...
Рейтинг: 0 / 0
Задача, запущенная в дочернем окне подвешивает интерфейс
    #38742178
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
капитанская дочкаАлексей Кпропущено...
Это то же самое.

тогда у меня наверное комп особенный раз у меня так работает или может быть потому что It uses the default task scheduler. Ага, вижу, в 4.5 такое добавили. Лучше поздно чем никогда.
...
Рейтинг: 0 / 0
Задача, запущенная в дочернем окне подвешивает интерфейс
    #38742197
Фотография МСУ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Что-то не понял, начальный код вполне рабочий. Автор, собери тестовый солюшен и прикрепи сюда.
...
Рейтинг: 0 / 0
Задача, запущенная в дочернем окне подвешивает интерфейс
    #38742273
iMrTidy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей К,

Parallel.Invoke - видимо имелось в виду замена:

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
            Task.Factory.StartNew(DoAbsolutelyNothing).ContinueWith(t =>
            {
                var window = new MainWindow();
                if (window.IsInitialized)
                    window.Show();

                Close();
            }, TaskScheduler.FromCurrentSynchronizationContext());



на что-то вроде:

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
            var parOpt = new ParallelOptions();
            parOpt.TaskScheduler = TaskScheduler.FromCurrentSynchronizationContext();
            DoAbsolutelyNothing();
            Parallel.Invoke(parOpt, () =>
                {
                    var window = new MainWindow();
                    if (window.IsInitialized)
                        window.Show();

                    Close();
                });



Очевидно, разница в том, что в первом случае код "полетит" дальше, не дожидаясь, когда окна "откроются и закроются", во втором случае, хоть исполнение и будет параллельным, но метод завершиться только, когда окна "открются и закроются". Визуально разницы нет, да и по ресурсам скорее тоже. Стоит отметить, что Parallel предствалеят большой интерес, особенно когда речь идет о параллельных циклах, но это уже пожалуй дело автора топика.
...
Рейтинг: 0 / 0
Задача, запущенная в дочернем окне подвешивает интерфейс
    #38742298
iMrTidy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
МСУЧто-то не понял, начальный код вполне рабочий. Автор, собери тестовый солюшен и прикрепи сюда.

Код действительно рабочий, однако

Код: c#
1.
_task = Task.Factory.StartNew(TestMethod);



будет запускаться в том же Thread, что и UI, а значит придется ждать 5 секунд, чего автор топика пытается избежать. Можно воспользоваться разными опциями для решения этой задачи. Например, как было указано (и пожалуй самый простой):

Код: c#
1.
_task = Task.Run(() => TestMethod());



Или, например, такие варианты:

Код: c#
1.
2.
var factory = new TaskFactory(TaskScheduler.Default);
_task = factory.StartNew(TestMethod);



Код: c#
1.
_task = Task.Factory.StartNew(() => { }).ContinueWith(t => TestMethod(), TaskScheduler.Default);
...
Рейтинг: 0 / 0
Задача, запущенная в дочернем окне подвешивает интерфейс
    #38742367
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
iMrTidyАлексей К,

Parallel.Invoke - видимо имелось в виду замена:

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
            Task.Factory.StartNew(DoAbsolutelyNothing).ContinueWith(t =>
            {
                var window = new MainWindow();
                if (window.IsInitialized)
                    window.Show();

                Close();
            }, TaskScheduler.FromCurrentSynchronizationContext());



на что-то вроде:

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
            var parOpt = new ParallelOptions();
            parOpt.TaskScheduler = TaskScheduler.FromCurrentSynchronizationContext();
            DoAbsolutelyNothing();
            Parallel.Invoke(parOpt, () =>
                {
                    var window = new MainWindow();
                    if (window.IsInitialized)
                        window.Show();

                    Close();
                });



Очевидно, разница в том, что в первом случае код "полетит" дальше, не дожидаясь, когда окна "откроются и закроются", во втором случае, хоть исполнение и будет параллельным, но метод завершиться только, когда окна "открются и закроются". Визуально разницы нет, да и по ресурсам скорее тоже. Стоит отметить, что Parallel предствалеят большой интерес, особенно когда речь идет о параллельных циклах, но это уже пожалуй дело автора топика.Понятно что можно через Parallel, но не вижу смысла запускать через него одну задачу.
...
Рейтинг: 0 / 0
Задача, запущенная в дочернем окне подвешивает интерфейс
    #38742369
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
МСУЧто-то не понял, начальный код вполне рабочий. Автор, собери тестовый солюшен и прикрепи сюда.Нет! Task из конструктора MainWindow будет запущен в UI потоке. Это один из маразмов TPL 4.0. В 4.5 это исправлено, добавлен человеческий Task.Run, который предложил(а) использовать капитанская дочка .
...
Рейтинг: 0 / 0
Задача, запущенная в дочернем окне подвешивает интерфейс
    #38742479
Фотография МСУ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей КМСУЧто-то не понял, начальный код вполне рабочий. Автор, собери тестовый солюшен и прикрепи сюда.Нет! Task из конструктора MainWindow будет запущен в UI потоке. Это один из маразмов TPL 4.0. В 4.5 это исправлено, добавлен человеческий Task.Run, который предложил(а) использовать капитанская дочка .
А да, постоянно забывают про этот UI поток. В WinRT, к примеру, нужен вот такой финт

Код: c#
1.
2.
var dispatcher = Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher;
await dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => {});



Причем, в остальных случаях Task.Factory.StartNew вполне приемлем. Вот нужно как-то во вью модель прокинуть этот диспетчер. А вью модель portable. Везде засада. Бесит.
...
Рейтинг: 0 / 0
Задача, запущенная в дочернем окне подвешивает интерфейс
    #38742509
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
МСУАлексей Кпропущено...
Нет! Task из конструктора MainWindow будет запущен в UI потоке. Это один из маразмов TPL 4.0. В 4.5 это исправлено, добавлен человеческий Task.Run, который предложил(а) использовать капитанская дочка .
А да, постоянно забывают про этот UI поток. В WinRT, к примеру, нужен вот такой финт

Код: c#
1.
2.
var dispatcher = Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher;
await dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => {});



Причем, в остальных случаях Task.Factory.StartNew вполне приемлем. Вот нужно как-то во вью модель прокинуть этот диспетчер. А вью модель portable. Везде засада. Бесит.Для синхронизации из любого места сделал статические SyncScheduler, SyncFactory и методы ContinueWithSync. Инициализирую SyncScheduler и SyncFactory при старте приложения. Теперь во ViewModel ничего прокидывать не надо.
...
Рейтинг: 0 / 0
Задача, запущенная в дочернем окне подвешивает интерфейс
    #38742512
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
МСУА вью модель portable.Для portable вместо static class использовать interface + DI .
...
Рейтинг: 0 / 0
Задача, запущенная в дочернем окне подвешивает интерфейс
    #38742520
monstrilla
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
всем спасибо. действительно, нужно было юзать дефолтный шедулер, на stackoverflow ответили. я вот всегда думал, что задача запускается всегда в новом потоке как Thread, например. Шилд обманывает, значит :(

авторTask.Factory.StartNew(TestMethod, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default);

Task.Run в 4.0 отсутствует ;)
...
Рейтинг: 0 / 0
Задача, запущенная в дочернем окне подвешивает интерфейс
    #38742530
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
monstrillaвсем спасибо. действительно, нужно было юзать дефолтный шедулер, на stackoverflow ответили. я вот всегда думал, что задача запускается всегда в новом потоке как Thread, например. Шилд обманывает, значит :(Все врут! Никому верить нельзя!
monstrillaTask.Run в 4.0 отсутствует ;)Об этом сразу было сказано. :-)
...
Рейтинг: 0 / 0
Задача, запущенная в дочернем окне подвешивает интерфейс
    #38742546
monstrilla
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Алексей К,

ну это больше капитанской дочке написано :)

хотел перейти на 4.5, чтоб освоить и юзать преимущества (а по слухам они есть) async-await-ов. Но в одном из проектов есть у меня хитропопое окошко, а в нем не менее хитропопый функционал. Так вот, в 4.0 работает, а в 4.5 перестает работать (несмотря на заявленную обратную совместимость). День убил - толку ноль, пришлось откатиться. Будет время соберу выложу как-нибудь тестовый солюшн, думаю, будет интересно.

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

а статью почитаю.
...
Рейтинг: 0 / 0
Задача, запущенная в дочернем окне подвешивает интерфейс
    #38742567
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
monstrillaеще вопросец, подскажите плз, хорошее чтиво по всем этим контекстам синхронизации, шедулерам, задачам. ибо плаваю, а пробелмы возникают регулрно. у шилда и нейгела только азы (по таскам), у трольсона вообще ничего, мсдн что-то совсем не нравится в этом плане. приходится какие-то обрывки гуглить и пытаться связать воедино.MSDN?
monstrillaа статью почитаю.Я там описал наиболее важные, на мой взгляд, моменты. Предложил несколько практических подходов, заточенных именно под .Net4.0 . Может чем поможет.
...
Рейтинг: 0 / 0
Задача, запущенная в дочернем окне подвешивает интерфейс
    #38742598
Фотография МСУ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей КМСУА вью модель portable.Для portable вместо static class использовать interface + DI .
Какой static class? Через какой интерфейс мне прокинуть во вью модель такой диспетчер и его енум?

Код: c#
1.
2.
var dispatcher = Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher;
await dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => { });
...
Рейтинг: 0 / 0
Задача, запущенная в дочернем окне подвешивает интерфейс
    #38742616
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
МСУАлексей Кпропущено...
Для portable вместо static class использовать interface + DI .
Какой static class?ViewModel ведь может обратиться к static class? Мне кажется может. :-)
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
class MyViewModel
{
    public void Execute()
    {
        Task.Factory
            .StartNew(() => { /*Тут ThreadPool-поток. Что то долгое*/ })
            .ContinueWithSync(t => { /*Тут UI-поток. Слава Хейлсбергу! Расширяющим методам Слава!*/ });
    }
}


МСУЧерез какой интерфейс мне прокинуть во вью модель такой диспетчер и его енум?Через самописный, но это для маразматиков. :-)
...
Рейтинг: 0 / 0
Задача, запущенная в дочернем окне подвешивает интерфейс
    #38742648
monstrilla
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
да, кстати, кому интересно и тем, кто столкнется с проблемой в будущем

Task in child window suspend UI

в ответе на вопрос есть линк(и), там более подробно расписано. прямые линки на всякий пожарный.

Why Starting a New Task in the Task Parallel Library (TPL) Doesn’t Always Start a New Thread
Why is TaskScheduler.Current the default TaskScheduler?
Is Task.Factory.StartNew() guaranteed to use another thread than the calling thread?
...
Рейтинг: 0 / 0
Задача, запущенная в дочернем окне подвешивает интерфейс
    #38742649
капитанская дочка
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
monstrillaTask.Run в 4.0 отсутствует ;)

а фурманов знает?
...
Рейтинг: 0 / 0
Задача, запущенная в дочернем окне подвешивает интерфейс
    #38742657
Фотография МСУ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей КМСУпропущено...
Какой static class?ViewModel ведь может обратиться к static class? Мне кажется может. :-)
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
class MyViewModel
{
    public void Execute()
    {
        Task.Factory
            .StartNew(() => { /*Тут ThreadPool-поток. Что то долгое*/ })
            .ContinueWithSync(t => { /*Тут UI-поток. Слава Хейлсбергу! Расширяющим методам Слава!*/ });
    }
}


Ну обратился, а дальше что? :) У нас же portable, никаких ссылок на Windows.winmd.

Алексей КМСУЧерез какой интерфейс мне прокинуть во вью модель такой диспетчер и его енум?Через самописный, но это для маразматиков. :-)
Писать свой диспетчер?

...
...
Рейтинг: 0 / 0
Задача, запущенная в дочернем окне подвешивает интерфейс
    #38742677
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
капитанская дочкаmonstrillaTask.Run в 4.0 отсутствует ;)

а фурманов знает?
...
Рейтинг: 0 / 0
Задача, запущенная в дочернем окне подвешивает интерфейс
    #38742686
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
МСУАлексей Кпропущено...
ViewModel ведь может обратиться к static class? Мне кажется может. :-)
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
class MyViewModel
{
    public void Execute()
    {
        Task.Factory
            .StartNew(() => { /*Тут ThreadPool-поток. Что то долгое*/ })
            .ContinueWithSync(t => { /*Тут UI-поток. Слава Хейлсбергу! Расширяющим методам Слава!*/ });
    }
}


Ну обратился, а дальше что? :) У нас же portable, никаких ссылок на Windows.winmd.А там вот так получается:

Код: c#
1.
ViewModel => TaskScheduler => SynchronizationContext => WPF (Win RT) Dispatcher


Тут и без своих интерфейсов аж две абстракции над Dispatcher. Так что portable не пострадает. :-)

Надо только где-нибудь глобально хранить ссылку на соответствующий TaskScheduler (или SynchronizationContext), и дело в шляпе..
...
Рейтинг: 0 / 0
25 сообщений из 46, страница 1 из 2
Форумы / WPF, Silverlight [игнор отключен] [закрыт для гостей] / Задача, запущенная в дочернем окне подвешивает интерфейс
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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