powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / WPF, Silverlight [игнор отключен] [закрыт для гостей] / [SL] Одна переменная для нескольких обработчиков
40 сообщений из 40, показаны все 2 страниц
[SL] Одна переменная для нескольких обработчиков
    #37803556
enigmatic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Могут ли возникнуть ошибки одновременного доступа к объекту в следующем коде?
Код выполняется в Silverlight.

Есть некий сервис, запрашивающий данные:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
public static class DataService{
	public static void GetSomeData(long id, Action<SomeData> callback){
		var client = new WebClient();
		client.DownloadStringAsync(uri);
		client.DownloadStringCompleted+=(s,ea)=>{
			if (ea.error != null)
				callback(ea.Result)
			else
				MessageBox.show(ea.error);
		}
	}
}

И есть код:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
pulbic void Test(){
	var asyncCounter = 0;
	foreach (var id in idList){
		asyncCounter++;
		DataService.GetSomeData(id, data=>{
			asyncCounter--;
			if (asyncCounter == 0){
				DoSmthElse(...);
			}
		});
	}
}

Здесь происходит несколько одновременных запросов, по завершении которых происходит вызов DoSmthElse();
Достигается это за счет использования переменной asyncCounter.

Будут ли проблемы при использовании этой одной переменной в обработчиках разных запросов в Silverlight?
...
Рейтинг: 0 / 0
[SL] Одна переменная для нескольких обработчиков
    #37803589
AlexeiK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
enigmatic,

предлагаешь всем подебажить твои отрывки кода в своих головах? тогда тебе в тему "Экстрасенсы говорят".
...
Рейтинг: 0 / 0
[SL] Одна переменная для нескольких обработчиков
    #37803638
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
enigmaticБудут ли проблемы при использовании этой одной переменной в обработчиках разных запросов в Silverlight?Да.

зы: Если DownloadStringCompleted выполняется в гуйном потоке - тогда нет. Надо смотреть мануал по этому событию.
...
Рейтинг: 0 / 0
[SL] Одна переменная для нескольких обработчиков
    #37803642
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
зы: Зря ты не послушал совета, и не стал использовать Task-и. Вместо этой байды применил бы Task.ContinueWhenAll . Дело твоё конечно, просто мысль...
...
Рейтинг: 0 / 0
[SL] Одна переменная для нескольких обработчиков
    #37803920
enigmatic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей КenigmaticБудут ли проблемы при использовании этой одной переменной в обработчиках разных запросов в Silverlight?Да.

зы: Если DownloadStringCompleted выполняется в гуйном потоке - тогда нет. Надо смотреть мануал по этому событию.
Хорошо. Значит, можно (пока) не беспокоиться.
http://msdn.microsoft.com/en-us/library/cc197953(v=vs.95).aspx The WebClient callback, which is raised when the HTTP response is returned, is invoked on the User Interface (UI) thread, and can be used to update the properties of UI elements.
Алексей Кзы: Зря ты не послушал совета, и не стал использовать Task-и. Вместо этой байды применил бы Task.ContinueWhenAll . Дело твоё конечно, просто мысль...Пока просто не могу этого сделать, т.к. пока не умею с тасками и пока в приоритете работа вообще не связанная с этим топиком.
Целью этого вопроса было убедиться, что вышеописанное не таит в себе скрытых граблей, на которые можно нарваться по неопытности.
В перспективе, нужно будет реализовать то же самое на Task (или Rx).

AlexeiKпредлагаешь всем подебажить твои отрывки кода в своих головах? тогда тебе в тему "Экстрасенсы говорят".Если хочется подебажить, то можно сделать тестовый солюшен с сервисом и обращением. Сделать?
...
Рейтинг: 0 / 0
[SL] Одна переменная для нескольких обработчиков
    #37836200
enigmatic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Попробовал через Task.ContinueWhenAll. Все отработало замечательно.
Прилагаю тестовый проект под 5-й SL.

Как бы сделать подобное под четвертым, где нет Task'ов?
Обновиться до пятого возможности пока нет.

Попробовал Rx под четвертым. Не получилось. Думаю, Rx предназначен скорее для работы с массивами данных генерируемыми мышкой, нежели с "действиями". Возможно не прав.

P.S. В тестовом проекте есть интересный момент - обработчики WebClient.DownloadStringCompleted отрабатывают после параметра Action<Tasks[]> continuationAction метода Task.Factory.ContinueWhenAll, хотя сначала выполняется код методов Get. Поэтому сначала выводится сообщение "Complete", а затем пара "Got 1-й/2-й".
...
Рейтинг: 0 / 0
[SL] Одна переменная для нескольких обработчиков
    #37837209
enigmatic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
enigmaticВ тестовом проекте есть интересный момент ...
Все правильно. Сначала выполняется код тасков, затем завершающий метод (continuationAction) и потом обработчики DownloadStringCompleted. Потому как continuationAction не будет ожидать обработчиков без соответствующей обработки.
...
Рейтинг: 0 / 0
[SL] Одна переменная для нескольких обработчиков
    #37837223
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
enigmaticВсе правильно.Всё не правильно. :-)

Вместо
Код: c#
1.
2.
3.
4.
5.
6.
        private void Get(Uri uri)
        {
            var client = new System.Net.WebClient();
            client.DownloadStringAsync(uri);
            client.DownloadStringCompleted += (s, ea) => Function(uri.ToString());
        }


должно быть что-то вроде
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
var t1 = Get(uri1);
var t2 = Get(uri2);

Task.Factory.ContinueWhenAll(new[] { t1, t2 }, tt => Dispatcher.BeginInvoke(() => MessageBox.Show("Complete")));

...

private Task Get(Uri uri)
{
    return Task.Factory.FromAsync(........);
}



зы: для синхронизации вместо явного вызова Dispatcher.BeginInvoke можно использовать контекст синхронизации.
...
Рейтинг: 0 / 0
[SL] Одна переменная для нескольких обработчиков
    #37837256
enigmatic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей КВсё не правильно. :-)Тот пример был написан на скорую руку и необдуманно. :)

Попробовал пример обертки EAP (Event-based Async Pattern) с MSDN ( линк (раздел Exposing Complex EAP Operations As Tasks) и линк ). Под нормальным дотнетом работает, под SL - виснет. Видимо, под SL опять тонкости, связанные с UI-потоком.
Прилагаю тестовые проекты под раром, они оба используют один и тот же "AsyncService"-класс для обертки EAP в таск:
ConsoleApplication1 - нормальный дотнет,
testTplTask - сильверлайт.
Если пробовать дебажить, то лучше начать с SL-проекта, чтобы поднять локальный вебсервер, на который будет потом коннектиться нормальный дотнет.
Алексей КВместо
Код: c#
1.
2.
3.
4.
5.
6.
        private void Get(Uri uri)
        {
            var client = new System.Net.WebClient();
            client.DownloadStringAsync(uri);
            client.DownloadStringCompleted += (s, ea) => Function(uri.ToString());
        }

должно быть что-то вроде
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
var t1 = Get(uri1);
var t2 = Get(uri2);

Task.Factory.ContinueWhenAll(new[] { t1, t2 }, tt => Dispatcher.BeginInvoke(() => MessageBox.Show("Complete")));

...

private Task Get(Uri uri)
{
    return Task.Factory.FromAsync(........);
}

Спасибо, попробую.Алексей Кзы: для синхронизации вместо явного вызова Dispatcher.BeginInvoke можно использовать контекст синхронизации.Тоже попробую.
...
Рейтинг: 0 / 0
[SL] Одна переменная для нескольких обработчиков
    #37837361
enigmatic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
enigmatic,

авторПрилагаю тестовые проекты под раром,
...
Рейтинг: 0 / 0
[SL] Одна переменная для нескольких обработчиков
    #37837750
enigmatic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей Кдолжно быть что-то вроде
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
var t1 = Get(uri1);
var t2 = Get(uri2);

Task.Factory.ContinueWhenAll(new[] { t1, t2 }, tt => Dispatcher.BeginInvoke(() => MessageBox.Show("Complete")));

...

private Task Get(Uri uri)
{
    return Task.Factory.FromAsync(........);
}


Похоже, Task.Factory.FromAsync(...) применяется для оборачивания таких методов как HttpWebRequest.BeginResponse/EndResponse (которые Async Programming Model), но не WebClient.DownloadStringAsync/DownloadStringCompleted (которые Event-based Async Pattern). По крайней мере, применить FromAsync к DownloadStringCompleted не получилось.
Для обертки EAP, судя по всему, предназначен TaskCompletionSource.
Но его использование под SL, похоже, вешает UI поток. Причем, похоже, TaskCompletionSource вешает его только под SL, но не в обычном .NET.
Гуглинг по использованию FromAsync для WebClient.DownloadStringCompleted не помог найти ничего нужного, но вместо этого дал отсылку к TaskCompletionSource ( секция Converting an Event-Based Pattern ).
...
Рейтинг: 0 / 0
[SL] Одна переменная для нескольких обработчиков
    #37837755
enigmatic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей К,

Не приходилось ли оборачивать WebClient с его DownloadStringAsync/DownloadStringCompleted в Task используя Task.Factory.FromAsync(...)?
...
Рейтинг: 0 / 0
[SL] Одна переменная для нескольких обработчиков
    #37837786
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
enigmaticПохоже, Task.Factory.FromAsync(...) применяется для оборачивания таких методов как HttpWebRequest.BeginResponse/EndResponse (которые Async Programming Model), но не WebClient.DownloadStringAsync/DownloadStringCompleted (которые Event-based Async Pattern). По крайней мере, применить FromAsync к DownloadStringCompleted не получилось.Согласен. Может как-то и можно, но у меня тоже не получилось. :-)

С другой стороны через TaskCompletionSource всё просто. Не запускал, но вроде должно работать:
Код: 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.
    public static class WebClientHelper
    {
        public static Task<string> DownloadStringAsyncEx(this WebClient wc, Uri uri)
        {
            var tcs = new TaskCompletionSource<string>();
            wc.DownloadStringCompleted += DownloadStringCompleted;
            wc.DownloadStringAsync(uri, tcs);
            return tcs.Task;    
        }

        static void DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
        {
            var wc = (WebClient)sender;
            wc.DownloadStringCompleted -= DownloadStringCompleted;

            var tcs = (TaskCompletionSource<string>)e.UserState;

            if (e.Cancelled)
            {
                tcs.SetCanceled();
                return;
            }

            if (e.Error != null)
            {
                tcs.SetException(e.Error);
                return;
            }

            tcs.SetResult(e.Result);
        }
    }


В случае с Силверлайтом - не знаю, надо думать, у нас тут жара аж капец... :-)
...
Рейтинг: 0 / 0
[SL] Одна переменная для нескольких обработчиков
    #37837832
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
enigmaticПочему бы не использовать HttpWebRequest.BeginGetResponse/EndGetResponse?
...
Рейтинг: 0 / 0
[SL] Одна переменная для нескольких обработчиков
    #37837900
enigmatic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей КС другой стороны через TaskCompletionSource всё просто. Не запускал, но вроде должно работать:
Код: 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.
    public static class WebClientHelper
    {
        public static Task<string> DownloadStringAsyncEx(this WebClient wc, Uri uri)
        {
            var tcs = new TaskCompletionSource<string>();
            wc.DownloadStringCompleted += DownloadStringCompleted;
            wc.DownloadStringAsync(uri, tcs);
            return tcs.Task;    
        }

        static void DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
        {
            var wc = (WebClient)sender;
            wc.DownloadStringCompleted -= DownloadStringCompleted;

            var tcs = (TaskCompletionSource<string>)e.UserState;

            if (e.Cancelled)
            {
                tcs.SetCanceled();
                return;
            }

            if (e.Error != null)
            {
                tcs.SetException(e.Error);
                return;
            }

            tcs.SetResult(e.Result);
        }
    }


Хм ... :) Использовать TaskCompletionSource в методе возврата Task. Хорошая мысль. Даже как-то не подумалось о такой возможности.

Алексей КВ случае с Силверлайтом - не знаю, надо думать, у нас тут жара аж капец... :-)Попробовал, благополучно виснет, причем только под SL.
То ли TaskCompleteSource вешает UI, то ли я что-то совсем не так делаю :)
Мы тоже кондиционеры на полную выкручиваем.

Алексей КПочему бы не использовать HttpWebRequest.BeginGetResponse/EndGetResponse?Надо будет попробовать. Но подгонять задачу (расправиться с WebClient'ом) под средства (Task'и) не наш метод же!
...
Рейтинг: 0 / 0
[SL] Одна переменная для нескольких обработчиков
    #37837909
enigmatic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
enigmaticПопробовал, благополучно виснет, причем только под SL...Тестовый код сейчас выглядит примерно так:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
public partial class MainPage
    {
        public MainPage()
        {
            InitializeComponent();

            var task = DownloadStringAsyncEx(new Uri("http://localhost:1732/data1.txt"));

            MessageBox.Show(string.Format("Got {0}", task.Result));
        }

        public Task<string> DownloadStringAsyncEx(Uri uri) {
            var tcs = new TaskCompletionSource<string>();
            var client = new WebClient();
            client.DownloadStringCompleted += (s, ea) => tcs.SetResult(ea.Result);
            client.DownloadStringAsync(uri, tcs);
            return tcs.Task;
        }
    }
...
Рейтинг: 0 / 0
[SL] Одна переменная для нескольких обработчиков
    #37837985
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
enigmaticНо подгонять задачу (расправиться с WebClient'ом) под средства (Task'и) не наш метод же!Боюсь, ничего хорошего из этого не выйдет. Мне кажется, WebClient с его встроенной синхронизацией и Task-и вещи взаимоисключающие.
...
Рейтинг: 0 / 0
[SL] Одна переменная для нескольких обработчиков
    #37838038
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
enigmaticТестовый код сейчас выглядит примерно так:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
    public partial class MainPage
    {
        public MainPage()
        {
            InitializeComponent();
            var task = DownloadStringAsyncEx(new Uri("http://localhost:1732/data1.txt"));
            MessageBox.Show(string.Format("Got {0}", task.Result));
        }


Так конечно, правильно что виснет. :-)
Надо как-то так:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
    public partial class MainPage
    {
        public MainPage()
        {
            InitializeComponent();
            
            DownloadStringAsyncEx(new Uri("http://localhost:1732/data1.txt"))
                .ContinueWith(t => Dispatcher.BeginInvoke(() =>
                       MessageBox.Show(string.Format("Got {0}", t.Result)
                )); // + обработку ошибок добавить
        }
...
Рейтинг: 0 / 0
[SL] Одна переменная для нескольких обработчиков
    #37838068
enigmatic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей К,

Но ведь консольное приложение отрабатывает нормально. Уверен, проблемы из-за отличия CLR SL от CLR обычного дотнета.
...
Рейтинг: 0 / 0
[SL] Одна переменная для нескольких обработчиков
    #37838816
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
enigmaticНо ведь консольное приложение отрабатывает нормально. Уверен, проблемы из-за отличия CLR SL от CLR обычного дотнета.Нет. Отличие в том, что приложение консольное. А в силверлайтном приложении возникает мёртвая блокировка. Ожидание завершения при обращении к свойству task.Result в конструкторе в гуйном потоке + событие завершения идёт в гуйном потоке == мёртвая блокировка.
...
Рейтинг: 0 / 0
[SL] Одна переменная для нескольких обработчиков
    #37838817
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Все отличия из-за того, что в Силверлайте DownloadStringCompleted синхронизирован с гуйным потоком. Но эти отличия были бы видны при сравнении с например WPF-ным приложением.
...
Рейтинг: 0 / 0
[SL] Одна переменная для нескольких обработчиков
    #37840697
SeVa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
enigmaticМогут ли возникнуть ошибки одновременного доступа к объекту в следующем коде?
Код выполняется в Silverlight.

Есть некий сервис, запрашивающий данные:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
public static class DataService{
	public static void GetSomeData(long id, Action<SomeData> callback){
		var client = new WebClient();
		client.DownloadStringAsync(uri);
		client.DownloadStringCompleted+=(s,ea)=>{
			if (ea.error != null)
				callback(ea.Result)
			else
				MessageBox.show(ea.error);
		}
	}
}

И есть код:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
pulbic void Test(){
	var asyncCounter = 0;
	foreach (var id in idList){
		asyncCounter++;
		DataService.GetSomeData(id, data=>{
			asyncCounter--;
			if (asyncCounter == 0){
				DoSmthElse(...);
			}
		});
	}
}

Здесь происходит несколько одновременных запросов, по завершении которых происходит вызов DoSmthElse();
Достигается это за счет использования переменной asyncCounter.

Будут ли проблемы при использовании этой одной переменной в обработчиках разных запросов в Silverlight?

Могут и будут. Асинхронные вызовы могут выполняться в разной последовательности, вызовы нужно делать с дополнительным параметром state, который нужно анализировать в обработчике. Помимо этого есть утечки памяти. При множественных вызовах webrequest - более предпочтительных вариант, тк нет лишней диспетчеризации в ui поток.
...
Рейтинг: 0 / 0
[SL] Одна переменная для нескольких обработчиков
    #37840698
SeVa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей КВсе отличия из-за того, что в Силверлайте DownloadStringCompleted синхронизирован с гуйным потоком. Но эти отличия были бы видны при сравнении с например WPF-ным приложением.

Привильно здесь deadlock, а task'и - унылый гумос. rx в разы удобней и лучше.В особенности для клиентских приложений
...
Рейтинг: 0 / 0
[SL] Одна переменная для нескольких обработчиков
    #37840750
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SeVaа task'и - унылый гумос. rx в разы удобней и лучше.В особенности для клиентских приложенийДля построения цепочки асинхронных операций таски удобны. Всё просто и ничего лишнего.

Покажи как будет выглядеть аналогичный код на Rx.
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
Task<int> F1()
{ return ... }

Task<int> F2(int v1)
{ return ... }

Task<int> F3(int v2)
{ return ... }

...


Task<int> Execute()
{
    return F1()
        .ContinueWith(t => F2(t.Result))
        .Unwrap()
        .ContinueWith(t => F3(t.Result))
        .Unwrap();
}
...
Рейтинг: 0 / 0
[SL] Одна переменная для нескольких обработчиков
    #37840798
SeVa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Элементарно
Код: c#
1.
2.
3.
4.
5.
var res = from t1 in Observable.Return(Task1())
              from t2 in Observable.Return(Task2())
              select t1+t2;
or
    Observable.Return(Task1()).And(Observable.Return(Task2()).Then((t1,t2) = > t1+t2)      



Пример и вопрос примитивный, тк task'и только под это заточены, а у rx возможностей больше
...
Рейтинг: 0 / 0
[SL] Одна переменная для нескольких обработчиков
    #37840809
ViPRos
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SeVa,

rx развивается?
...
Рейтинг: 0 / 0
[SL] Одна переменная для нескольких обработчиков
    #37840821
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SeVaЭлементарно
Код: c#
1.
2.
3.
4.
5.
var res = from t1 in Observable.Return(Task1())
              from t2 in Observable.Return(Task2())
              select t1+t2;
or
    Observable.Return(Task1()).And(Observable.Return(Task2()).Then((t1,t2) = > t1+t2)      

Неправильно. Метод Task2() должен принимать результат выполнения метода Task1(). Для чистоты эксперивента возьми за основу методы F1, F2 и F3 из моего примера. Преобразуй возвращаемые ими Task в IObservable (вроде это несложно) и покажи как будет выглядеть цепочка вызовов на Rx. Мне правда интересно. :-)

SeVaПример и вопрос примитивный, тк task'и только под это заточены, а у rx возможностей большеБольшего не требуется. Мне надо чтобы именно это описывалось максимально удобным кодом.
...
Рейтинг: 0 / 0
[SL] Одна переменная для нескольких обработчиков
    #37840846
SeVa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей КSeVaЭлементарно
Код: c#
1.
2.
3.
4.
5.
var res = from t1 in Observable.Return(Task1())
              from t2 in Observable.Return(Task2())
              select t1+t2;
or
    Observable.Return(Task1()).And(Observable.Return(Task2()).Then((t1,t2) = > t1+t2)      

Неправильно. Метод Task2() должен принимать результат выполнения метода Task1(). Для чистоты эксперивента возьми за основу методы F1, F2 и F3 из моего примера. Преобразуй возвращаемые ими Task в IObservable (вроде это несложно) и покажи как будет выглядеть цепочка вызовов на Rx. Мне правда интересно. :-)

SeVaПример и вопрос примитивный, тк task'и только под это заточены, а у rx возможностей большеБольшего не требуется. Мне надо чтобы именно это описывалось максимально удобным кодом.

Код: sql
1.
2.
3.
4.
5.
var res = from t1 in Observable.Return(Task1())
              from t2 in Observable.Return(Task2(t1))
              from t3 in Observable.Return(Task2(t2))
              etc
              select t48;


Частная задача, а требуется значительно больше. Таски Без поддержки всех операторов linq
- жалкая полова.
Чуть усложним. Покажи код, когда Task1&Task2 выполняются последовательно,Task3 параллено им, все они возвращают коллекции и нужно определить минимальное и максимальное значение в объединенном наборе.Плюс должна быть обработка ошибок.
...
Рейтинг: 0 / 0
[SL] Одна переменная для нескольких обработчиков
    #37840856
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SeVa
Код: sql
1.
2.
3.
4.
5.
var res = from t1 in Observable.Return(Task1())
              from t2 in Observable.Return(Task2(t1))
              from t3 in Observable.Return(Task2(t2))
              etc
              select t48;

Ок, пасиб.
SeVaТаски Без поддержки всех операторов linq
- жалкая полова.Да ну. Это уже бантики.
SeVaЧуть усложним. Покажи код, когда Task1&Task2 выполняются последовательно,Task3 параллено им, все они возвращают коллекции и нужно определить минимальное и максимальное значение в объединенном наборе.Плюс должна быть обработка ошибок.
Код: 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.
var t1 = Task1()
    .ContinueWith(t => Task2(t.Result))
    .Unwrap();

var t2 = Task3();

Task.Factory
    .ContunueWhenAll(
        new[] {t1, t2},
        tt =>
        {
              var items = t1.Result.Concat(t2.Result);
              Console.WriteLine(items.Min());
              Console.WriteLine(items.Max());
        }
    )
    .LogExceptions();

////////////////////

public static class TaskHelper
{
    public static void LogExceptions(this Task task)
    {
        if (task.Exception != null)
            Log.AddException(task.Exception);
    }
}
...
Рейтинг: 0 / 0
[SL] Одна переменная для нескольких обработчиков
    #37841017
SeVa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ViPRosSeVa,

rx развивается?

Да, есть уже бета 2.0 и будет native rx для winrt
...
Рейтинг: 0 / 0
[SL] Одна переменная для нескольких обработчиков
    #37841036
SeVa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей КSeVa
Код: sql
1.
2.
3.
4.
5.
var res = from t1 in Observable.Return(Task1())
              from t2 in Observable.Return(Task2(t1))
              from t3 in Observable.Return(Task2(t2))
              etc
              select t48;

Ок, пасиб.
SeVaТаски Без поддержки всех операторов linq
- жалкая полова.Да ну. Это уже бантики.
SeVaЧуть усложним. Покажи код, когда Task1&Task2 выполняются последовательно,Task3 параллено им, все они возвращают коллекции и нужно определить минимальное и максимальное значение в объединенном наборе.Плюс должна быть обработка ошибок.
Код: 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.
var t1 = Task1()
    .ContinueWith(t => Task2(t.Result))
    .Unwrap();

var t2 = Task3();

Task.Factory
    .ContunueWhenAll(
        new[] {t1, t2},
        tt =>
        {
              var items = t1.Result.Concat(t2.Result);
              Console.WriteLine(items.Min());
              Console.WriteLine(items.Max());
        }
    )
    .LogExceptions();

////////////////////

public static class TaskHelper
{
    public static void LogExceptions(this Task task)
    {
        if (task.Exception != null)
            Log.AddException(task.Exception);
    }
}


Весьма замысловато и неудобно, тк с полученными результатами можно работать только через одно место. C rx это делается в одну строчку
...
Рейтинг: 0 / 0
[SL] Одна переменная для нескольких обработчиков
    #37842090
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SeVaВесьма замысловато и неудобно, тк с полученными результатами можно работать только через одно место.Дискомфорта не испытываю. Если захочется LINQ - таски всегда можно преобразовать в IObservable.
...
Рейтинг: 0 / 0
[SL] Одна переменная для нескольких обработчиков
    #37843401
SeVa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей КSeVaВесьма замысловато и неудобно, тк с полученными результатами можно работать только через одно место.Дискомфорта не испытываю. Если захочется LINQ - таски всегда можно преобразовать в IObservable.

Таски - процедурный стиль, rx - фукциональный. DbReader vs linq
...
Рейтинг: 0 / 0
[SL] Одна переменная для нескольких обработчиков
    #37875792
enigmatic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей КenigmaticНо ведь консольное приложение отрабатывает нормально. Уверен, проблемы из-за отличия CLR SL от CLR обычного дотнета.Нет. Отличие в том, что приложение консольное. А в силверлайтном приложении возникает мёртвая блокировка. Ожидание завершения при обращении к свойству task.Result в конструкторе в гуйном потоке + событие завершения идёт в гуйном потоке == мёртвая блокировка.Хотелось бы поблагодарить автора за этот ответ, т.к. этот ответ я пропустил.
Вот здесь дали почти такой же, потом я собрался перепостить его сюда, а оказалось, что он здесь уже есть =)

Алексей К , мне бы ваш опыт в понимании именно возникающего дедлока =)
SeVaМогут и будут. Асинхронные вызовы могут выполняться в разной последовательности, вызовы нужно делать с дополнительным параметром state, который нужно анализировать в обработчике. Помимо этого есть утечки памяти. При множественных вызовах webrequest - более предпочтительных вариант, тк нет лишней диспетчеризации в ui поток.>Асинхронные вызовы могут выполняться в разной последовательности
>вызовы нужно делать с дополнительным параметром state
Чтобы иметь возможность их различать. При описанном в первом посте подходе этого не требуется.
>Помимо этого есть утечки памяти
Я бы попросил поподробнее, пожалуйста.
>При множественных вызовах webrequest - более предпочтительных вариант, тк нет лишней диспетчеризации в ui поток.
Согласен.
...
Рейтинг: 0 / 0
[SL] Одна переменная для нескольких обработчиков
    #37875806
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
enigmatic>Асинхронные вызовы могут выполняться в разной последовательности
>вызовы нужно делать с дополнительным параметром state
Чтобы иметь возможность их различать. При описанном в первом посте подходе этого не требуется.
Асинхронные операции могут завершится не в том порядке, в котором их запускали. Часто в GUI-приложении нужен результат только последнего запущенного таска, если произошло несколько запусков одновременно. Одним из решений является передача state object с идентификатором, который проверяется при завершении операции. Мне же больше нравится такое решение:
Идеальный код :-)
Код: 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.
class MyClass
{
    Task<int> GetDataLastTask;

    void Execute() // как правило это вызывается в гуйном потоке
    {
        GetDataLastTask = GetData();
        GetDataLastTask
            .ContinueWith(t => // как правило это синхронизировано с гуйным потоком
            {
                if (t != GetDataLastTask)
                {
                    t.ThrowIfException();
                    return;
                }
                 
                // тут работаем с t.Result

            })
            .LogExceptions();
    }

    Task<int> GetData()
    {
        return Task.Factory....
    }
}

public static class TaskHelper
{
    public static void LogExceptions(this Task task)
    {
        task.ContinueWith(t =>
        {
            if (t.Exception != null)
                Log.AddException(t.Exception);
        });
    }

    public static void ThrowIfException(this Task task)
    {
        if (task.Exception != null)
            throw new AggregateException(task.Exception);
    }
}

Это решение, наверное, не на все случаи жизни, но часто его достаточно. Главное, что оно не зависит от предметной области, в отличие от решения через state object.

автор>Помимо этого есть утечки памяти
Я бы попросил поподробнее, пожалуйста.Я утечек памяти не заметил.
...
Рейтинг: 0 / 0
[SL] Одна переменная для нескольких обработчиков
    #37876269
enigmatic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей КАсинхронные операции могут завершится не в том порядке, в котором их запускали. Часто в GUI-приложении нужен результат только последнего запущенного таска, если произошло несколько запусков одновременно. Одним из решений является передача state object с идентификатором, который проверяется при завершении операции.
Да, конечно. Но при описанном подходе ничего проверять не нужно, т.к. колбек таска жестко связан с его вызовом, и если нам нужно сделать обработку только последнего запущенного таска, то мы просто описываем эту обработку в колбеке последнего таска.
Напротив, если использовать события - то обработчики не связаны с запрашивающими методами и нам нужны object state, чтобы понять, какой из обработчиков какому запросу соответствует.

Алексей КМне же больше нравится такое решение:
Идеальный код :-)
Код: 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.
class MyClass
{
    Task<int> GetDataLastTask;

    void Execute() // как правило это вызывается в гуйном потоке
    {
        GetDataLastTask = GetData();
        GetDataLastTask
            .ContinueWith(t => // как правило это синхронизировано с гуйным потоком
            {
                if (t != GetDataLastTask)
                {
                    t.ThrowIfException();
                    return;
                }
                 
                // тут работаем с t.Result

            })
            .LogExceptions();
    }

    Task<int> GetData()
    {
        return Task.Factory....
    }
}

public static class TaskHelper
{
    public static void LogExceptions(this Task task)
    {
        task.ContinueWith(t =>
        {
            if (t.Exception != null)
                Log.AddException(t.Exception);
        });
    }

    public static void ThrowIfException(this Task task)
    {
        if (task.Exception != null)
            throw new AggregateException(task.Exception);
    }
}

Это решение, наверное, не на все случаи жизни, но часто его достаточно. Главное, что оно не зависит от предметной области, в отличие от решения через state object.
Если честно, меня терзают смутные сомнения, что у меня то же самое, но не на тасках =)
Но таски (точнее не самими тасками, а контексте использования потоков), как видите, не пошли сразу и сходу, т.к. нужно понимать особенности диспетчеризации потоков, чем я пока похвастаться не могу :)
Я еще посмотрю ваш идеальный код (когда поумнею :))
...
Рейтинг: 0 / 0
[SL] Одна переменная для нескольких обработчиков
    #37876302
enigmatic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
enigmatic...
Да, конечно. Но при описанном подходе ничего проверять не нужно, т.к. колбек таска жестко связан с его вызовом, и если нам нужно сделать обработку только последнего запущенного таска, то мы просто описываем эту обработку в колбеке последнего таска.
Напротив, если использовать события - то обработчики не связаны с запрашивающими методами и нам нужны object state, чтобы понять, какой из обработчиков какому запросу соответствует.Что-то я посмотрел первый пост и понял, что описанное неочевидно. Если хотите, я могу сделать выполнение обработки последнего запущенного таска и/или последнего принятого ответа. Будет показательный пример.
...
Рейтинг: 0 / 0
[SL] Одна переменная для нескольких обработчиков
    #37876398
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
enigmaticДа, конечно. Но при описанном подходе ничего проверять не нужно, т.к. колбек таска жестко связан с его вызовом, и если нам нужно сделать обработку только последнего запущенного таска, то мы просто описываем эту обработку в колбеке последнего таска.На каждый асинхронный вызов создаётся новый объект таска. Мы подписываемся на результат выполнения всех запущенных тасков, например, через ContinueWith. Может оказаться, что последний запущенный таск не будет последним выполненным. Типичная ситуация, master-detail. Может оказаться, что текущей записи в списке master будет показан detail "предыдущей текущей" записи в master.
enigmaticНапротив, если использовать события - то обработчики не связаны с запрашивающими методами и нам нужны object state, чтобы понять, какой из обработчиков какому запросу соответствует.Тут ситуация аналогична, просто единственным способом будет передача state object.
enigmaticЕсли хотите, я могу сделать выполнение обработки последнего запущенного таска и/или последнего принятого ответа. Будет показательный пример.Я ухожу в отпуск, не обещаю что посмотрю. :-)
...
Рейтинг: 0 / 0
[SL] Одна переменная для нескольких обработчиков
    #37876401
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
enigmaticЕсли честно, меня терзают смутные сомнения, что у меня то же самое, но не на тасках =)Ничего удивительного. :-) Таски всего лиш более удобная реализация всем давно известных концепций. :-)
...
Рейтинг: 0 / 0
[SL] Одна переменная для нескольких обработчиков
    #37876445
enigmatic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей КНа каждый асинхронный вызов создаётся новый объект таска. Мы подписываемся на результат выполнения всех запущенных тасков, например, через ContinueWith. Может оказаться, что последний запущенный таск не будет последним выполненным. Типичная ситуация, master-detail. Может оказаться, что текущей записи в списке master будет показан detail "предыдущей текущей" записи в master.Хорошо, я все перепроверю.

Алексей КЯ ухожу в отпуск, не обещаю что посмотрю. :-)Приятного отдыха! :)
...
Рейтинг: 0 / 0
40 сообщений из 40, показаны все 2 страниц
Форумы / WPF, Silverlight [игнор отключен] [закрыт для гостей] / [SL] Одна переменная для нескольких обработчиков
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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