
Arseniy
18.03.2017
18:09:35

ACx0
18.03.2017
18:09:51

Летучая
18.03.2017
18:10:33
await Task.Run(() =>
{
this.loadAction?.Invoke(this);
});
Что будет происходить при выполнении этого кода, поясните плз. Если я пишу this.loadAction(this), вылезает ComException. Если пишу чз Invoke, эксепшн не вылезает. Почему? Invoke данный метод в мейнтреде дёргает? Но судя по тому, что изменения UI в loadAction вызывают опять же ComException, вроде бы это не мейн тред.
Почему в этом случае
await Task.Run(() => { this.loadAction(this); });
падение, а в случае выше — нет?

code4aman
18.03.2017
18:10:40
https://twitter.com/rauchg/status/842950503709327360 кто нить в курсе?

Google

Arseniy
18.03.2017
18:10:58
@Hi10pH264 у тя есть тред1 и есть тред2, они отличаются каким-то контекстом.
если скопировать весь контекст из тред1 в тред2, чем тебе это не место вызова?

ACx0
18.03.2017
18:11:04
Я всё никак не пойму, как оно устроено.
А работает оно, похоже, абсолютно неочевидным образом, поэтому понять это необходимо, прежде чем использовать.

Arseniy
18.03.2017
18:11:39
работает сложно - это 100%, надо знать подноготную

Летучая
18.03.2017
18:11:44
А. Или я там await писал...

Ilya
18.03.2017
18:11:57
смотри, ещё раз, на пальцах: у тебя есть await. Весь метод разбивается на до и после. то что до - выполняется сразу, потом УПРАВЛЕНИЕ возвращается. Когда таск завершается - второй методо передаётся в SyncronizationContext, который был захвачен в первом методе. Этот synchronizationContext запускает этот метод (второй) на том потоке, на котором был запущен первый метод.
это в случае НЕ консольного приложения, когда есть SynchonizationContext и ConfigureaAwait(true) (по умолчанию)

ACx0
18.03.2017
18:14:01
Есть вообще какая-нибудь статья, где написано вообще всё о том, как работает async/await? Хоть в 200 страниц, но чтобы всё расписано было.

code4aman
18.03.2017
18:15:18
ildasm.exe

ACx0
18.03.2017
18:15:40

Arseniy
18.03.2017
18:16:32

Летучая
18.03.2017
18:16:59

Ilya
18.03.2017
18:17:45

Google

Летучая
18.03.2017
18:18:02
public void Main() {
this.DoStuff();
}
private async void DoStuff() {
await PerformTask;
}
Вот при таком коде ПерформТаск будет выполняться в главном потоке же?

Arseniy
18.03.2017
18:18:14

Летучая
18.03.2017
18:19:01
Чтобы выполнить таск в треде из ThreadPool, надо Task.Run(() => { PerformTask(); });?

Arseniy
18.03.2017
18:20:15
да не

ACx0
18.03.2017
18:20:45
Ну и ещё раз попробую пример тот написать.
Мы в async методе, который вызван откуда-то, например из Parallel.For();
В нём мы достигаем вызова с await, следующей строкой используется результат.
Вот в момет достижения await происходит понимание, что выполнение затянулось и происходят неочевидные вещи. Какие?
// Управление возвращается обратно, потом по сигналу завершения Awaitable метод продолжается. Но он уже вернул управление. Или это не return и он висит где-то в ожидании? Или пересоздаётся? Вот что вообще происходит, когда встречается Awaitable, которое не сразу возвращает значение?

Arseniy
18.03.2017
18:21:24
@Worldbeater если ты не предпримешь дополнительных усилий у тебя любой правильно написанный таск улетит на работу в стандартный шедулер

ACx0
18.03.2017
18:21:37

Arseniy
18.03.2017
18:22:31

ACx0
18.03.2017
18:23:31

Arseniy
18.03.2017
18:24:56
да никакой не итерацией
параллел.фор принимает на вход параметры, создает N традов и начинает на них выполнять операции
это такое высокоуровневое описание. внутри он исполняет лямбды на пуле, емнип

ACx0
18.03.2017
18:28:07

Arseniy
18.03.2017
18:30:40
ты какбэ кад прикладывай, а то хз, чо ты пытаешься представить
https://referencesource.microsoft.com/#mscorlib/system/threading/Tasks/Parallel.cs,0a55781a1c82cafe
внутри тоже таски, хоть и непубличные

ACx0
18.03.2017
18:34:06
private static async Task<int> AsyncRequest() {
await Task.Delay(1000);
return 10;
}
private static async Task<int> AsyncMethod(int id) {
int res = await AsyncRequest(); // What's going on from here?
res *= id;
return res;
}
static void Main(string[] args) {
Parallel.For(0, 10, i => {
Console.WriteLine(string.Format("Requesting number from {0}", i));
int Res = Task.Run(async () => await AsyncMethod(i)).Result;
Console.WriteLine(string.Format("Requested number: {0}. From: {1}", Res, i));
});
Console.Read();
}
Вместо AsyncRequest поставить какой-нибудь REST запрос и разбор ответа.

Google

Arseniy
18.03.2017
18:37:33
var http = new HttpClient();
var response = await http.GetAsStringAsync("yobaURL").ConfigureAwait(false);
return Parse(response)
?

ACx0
18.03.2017
18:38:22
На уровне. Насчёт .ConfigureAwait(false) не уверен.
Не против узнать оба варианта.

Arseniy
18.03.2017
18:38:59
в смысле

ACx0
18.03.2017
18:39:18
Как будет с ним и без него.

Arseniy
18.03.2017
18:40:14
ну протестируй. так-то если тебе надо вернуться в оригинальное место, то тебе надо дожидаться таску, которая оборачивает эти строчки
сам помнимаешь, что await без контекста async не заюзать

ACx0
18.03.2017
18:41:52
Как я протестирую, если дебаггер не показывает как оно работает?

Arseniy
18.03.2017
18:44:14
ну а как ты собрался тестировать многопоточные приложения дебаггером?
вот давай самое простое
создай UI приложение и повесь там на онБоттонКлик 100500 задач, которые просто засыпают с разным (но небольшим сроком паячки)

ACx0
18.03.2017
18:46:16
Снова всё не по теме.
У меня вопрос конкретно в том месте, где написан комментарий.
Я бы написал, что мне не важно, откуда вызван этот метод, но, похоже, важно.

Arseniy
18.03.2017
18:46:43
какой комментарий?

ACx0
18.03.2017
18:47:00

Arseniy
18.03.2017
18:47:28
бля, постите кад на пастин или гист
твоя задача падает запускается и падает в пул

ACx0
18.03.2017
18:48:18
http://pastebin.com/Sw7zsimz

Arseniy
18.03.2017
18:48:20
когда она закончится шедулится еще одна задача
res *= id;
return res
в вызывающем контексте
где зашедулится первая задача можно понять тока раскурив подноготную

Google

ACx0
18.03.2017
18:51:22
Слишком кратко, не понятно.

Pichugin
18.03.2017
18:51:26
https://www.youtube.com/watch?v=p6erF2uBQgQ

ACx0
18.03.2017
18:52:15

Arseniy
18.03.2017
18:53:46
https://referencesource.microsoft.com/#mscorlib/system/threading/Tasks/Task.cs,5885
ничо ни откуда не падает.
первая задача выполнится на стандартном шедулере, потому что там отработает делай

ACx0
18.03.2017
18:55:20
Изначально таск попал в пул, где попал в поток.
Потом идёт строка с await.
1. Куда отправляется (и где исполняется) Request.
2. Что происходит с методом, пока это происходит.
3. Что происходит с Таском, пока всё это происходит.

Arseniy
18.03.2017
18:55:26
потом ее результат вернется в контекст старта (потому что это дефолтное поведение)
какой блять пул, какой блять поток

ACx0
18.03.2017
18:56:10

Admin
ERROR: S client not available

Arseniy
18.03.2017
18:56:12
таск - это замкнутая лямда с параметрами

Ilya
18.03.2017
18:56:52
для интереса?

ACx0
18.03.2017
18:57:24

Ilya
18.03.2017
18:57:33
зачем такая конструкция Task.Run(async () => await AsyncMethod(i)).Result?
почему не написать AsyncMethod(i).Result?

ACx0
18.03.2017
18:58:01

Arseniy
18.03.2017
18:58:22

ACx0
18.03.2017
18:58:34
Так везде написано, что это заставляет вызывающий поток ждать, а await ждёт его освобождения и всё.

Arseniy
18.03.2017
18:58:46
не поток

Google

Arseniy
18.03.2017
18:58:51
ПРОДОЛЖЕНИЕ

ACx0
18.03.2017
18:58:52
Ну или не поток

Arseniy
18.03.2017
18:59:08
я уже 10 раз сказал, что ты бьешь своё флоу выполнения на кучку задач

ACx0
18.03.2017
18:59:16
Можно в самих терминах написать? Я не знаю русских эквивалентов.

Arseniy
18.03.2017
18:59:16
которые триггерят друг друга

Ilya
18.03.2017
18:59:20
ты либо читаешь не те треды, либоо неправильно их понимаешь)
Parallel.For(0, 10, i => {
Console.WriteLine(string.Format("Requesting number from {0}", i));
int Res = AsyncMethod(i).Result;
Console.WriteLine(string.Format("Requested number: {0}. From: {1}", Res, i));
});

Arseniy
18.03.2017
18:59:45

Ilya
18.03.2017
19:00:28
смотри что у тебя происходит, тут нет ничего сложного

Летучая
18.03.2017
19:00:47
Оч интересно сегодня в чате

Ilya
18.03.2017
19:00:54
ты запускаешь ParallelFor - он создаёт столько потоков, сколько у тебя логических ядер у процессора

ACx0
18.03.2017
19:01:34
А, ну да, тут же уже потоки создаются, тут действительно Task не нужен.

Ilya
18.03.2017
19:01:36
на каждом из этих потоков вызывается метод, который ты передал, отличаются только параметры (i)

ACx0
18.03.2017
19:01:53

Ilya
18.03.2017
19:02:21
в моём варианте (без task.run int Res = AsyncMethod(i).Result;) происходит следующее:
код, Console.WriteLine(string.Format("Requesting number from {0}", i));
выполняется в одном из четырёх потоков, котроые создал ParallelFor, затем идёт вызов метода, в том же потоке

Летучая
18.03.2017
19:03:21

ACx0
18.03.2017
19:03:26
(можно ли считать, что P.F заменяет T.R в данном случае?)

Ilya
18.03.2017
19:04:12
дальше когда вызывается Task.Delay(1000) УПРАВЛЕНИЕ возвращается обратно и вызывается геттер свойства Result

Arseniy
18.03.2017
19:04:36

ACx0
18.03.2017
19:05:27
Эта группа больше не существует