Рассмотрим следующие коды C
var L1 =
Task.Run(() =>
{
return Task.Run(() =>
{
return Task.Run(() =>
{
return Task.Run(() =>
{
return new Dummy();
});
});
});
});
var L2 =
Task.Run(async() =>
{
return await Task.Run(async() =>
{
return await Task.Run(async() =>
{
return await Task.Run(async() =>
{
return new Dummy();
});
});
});
});
var L3 =
Task.Run(async() =>
{
return Task.Run(async() =>
{
return Task.Run(async() =>
{
return Task.Run(async() =>
{
return new Dummy();
});
});
});
});
var r1 = L1.Result;
var r2 = L2.Result;
var r3 = L3.Result;
# ===================== =======================================
на первый взгляд, L1, L2 и L3 все выглядит как
Task<Task<Task<Task<Dummy>>>>
Оказывается, L1 и L2 просто Task<Dummy>
Так, я смотрю на MSDN для Task.Run
(мой перегруженный Task.Run является: Task.Run<TResult>(Func<Task<TResult>>)
)
MSDN говорит:странное поведение компилятор при смешивании Task.Run с асинхронным/ждут ключевого слова
Возвращаемое значение является следующим: Задача (TResult), который представляет собой прокси-сервер для выполнения этой задачи (TResult), возвращаемой функцией.
Он также говорит, что в примечаниях:
Метод
Run<TResult>(Func<Task<TResult>>)
используется языком компиляторов для поддержки асинхр и ждет ключевых слов. Не предполагается, что вызывается непосредственно из кода пользователя.
Таким образом, похоже, что я не должен использовать этот перегруженный Task.Run в моем коде,
и если я делаю, компилятор удалит лишние слои Task<Task<Task<...<TResult>>>>
и просто дать вам Task<TResult>
If указателя мыши над L1 и L2, он говорит вам, что это Task<Dummy>
, не мой
ожидается Task<Task<Task<Task<Dummy>>>>
до сих пор так хорошо, пока я не смотрю на L3
L3 выглядит почти точно так же, как L1 и L2. Разница заключается в том:
L3 имеет только async
ключевое слово, а не await
, в отличие от L1 и L2, где L1 имеет ни один из них и L2 имеет оба
Удивительно, L3 теперь рассматривается как Task<Task<Task<Task<Dummy>>>>
, в отличие от L1 и L2 , где оба считаются Task<Dummy>
Мои вопросы:
1.
Что заставляет компилятор для лечения L3 отличается от L1 и L2. Почему просто добавление 'async'
в L1 (или удаление await
из L2) заставляет компилятор обрабатывать его по-разному?
2.
Если вы больше каскадируете Task.Run to L1/L2/L3, значит, сбой Visual Studio. Я использую VS2013, если я каскадирую 5 или более слоев Task.Run, он сработает. 4 слоя - это лучшее, что я могу получить, поэтому в качестве примера я использую 4 слоя. Это только я ? Что случилось с компилятором при переводе Task.Run?
Благодаря
У меня 7 уровней глубокой, а затем VS2013 не реагировал. Это может быть один из моих расширений (в частности, Resharper), который виноват; Я не дошел до этого. –