Всегда ли ExecutionContext переходит в Task.Run или Parallel.ForEach?C#

Место общения программистов C#
Ответить
Anonymous
 Всегда ли ExecutionContext переходит в Task.Run или Parallel.ForEach?

Сообщение Anonymous »

В приложении ASP.NET я много чего делаю с помощью Task.Run и Parallel.ForEach. В некоторые моменты я могу пройти 2-3 уровня в глубину:
// This is in a controller somewhere (i.e. so the Request object is in scope)

Task.Run(() => {
Parallel.ForEach(things, t => {
Task.Run(() => {
Parallel.ForEach(otherThings, t => {
// etc..

Это преувеличение (и глупая идея; я это понимаю), но вопрос в том, должен ли объект Request быть доступен на всем протяжении этого этапа?< /p>
Я много читал и понял, что ExecutionContext должен «перетекать» во весь этот код (если вы явно не запретите это).
Первый Task.Run должен получить тот же ExecutionContext, что и «внешний» код. Он должен передать это первому Parallel.ForEach и так далее. Насколько я понимаю, код в самом низу этого стека должен иметь доступ к тем же данным, что и исходный вызывающий код.
В моей ситуации я получаю странные нулевые ошибки на некоторых уровнях, когда ясно, что блок не получил переданный ему ExecutionContext. Например, внутри Task.Run все имеет значение null, но вне его не имеет значения null. Ошибки соответствуют определенному коду, но я не вижу, чем этот код отличается от другого кода, в котором ошибка не возникает.
Я неправильно понимаю некоторые нюансы ExecutionContext поток?
Обновление: Вот какой-то глупый, надуманный код:
void Main()
{
var things = new string[] { "foo", "bar", "baz" };

Console.WriteLine(1);
Task.Run(() =>
{
Console.WriteLine(2);
Parallel.ForEach(things, t =>
{
Console.WriteLine(3);
Task.Run(() =>
{
Console.WriteLine(4);
Parallel.ForEach(things, t =>
{
Console.WriteLine(5);
Console.WriteLine(t);
});
});
});
});
}

Конечно, я получаю выходные данные глубиной пять уровней. Таким образом, самый внутренний Parallel.ForEach содержит правильные данные в вещах (которые были установлены в вызывающем коде).
Что может привести к тому, что этого не произойдет?
Обновление: Основываясь на комментарии, я проверил теорию о том, что запрос завершался раньше, пока Задача все еще выполнялась. Я думаю, именно это и происходит, потому что я не использовал async/await. Это означало, что запрос не дождался завершения задачи, и объект Request исчез.
Вот мой тестовый код, КОТОРЫЙ РАБОТАЕТ (то есть, в этом конкретном тестовом примере он продолжает работать). навсегда...)
[Route("test")]
public async Task Test()
{
await Task.Run(() =>
{
var counter = 0;
while (true)
{
counter++;
ServiceLocator.Current.GetInstance().HttpContext.Items.Add(counter.ToString(), "foo");
Debug.WriteLine(counter);
}

});

return "OK";
}

Это НЕ работает — при попытке работы с HttpContext выдается нулевая ссылка. Поскольку я не ждал завершения задачи, она пыталась запуститься после завершения запроса, а запрос был нулевым.
[Route("test")]
public string Test()
{
Task.Run(() =>
{
var counter = 0;
while (true)
{
counter++;
ServiceLocator.Current.GetInstance().HttpContext.Items.Add(counter.ToString(), "foo");
Debug.WriteLine(counter);
}

});

return "OK";
}


Подробнее здесь: https://stackoverflow.com/questions/792 ... el-foreach
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»