Во-первых, я хотел бы подчеркнуть, что то, что вы пытаетесь сделать, вероятно, плохая идея.HostingEnvironment.QueueBackgroundWorkItem
будет не предотвращать создание потоков или ограничивать истощение пула потоков.Это на самом деле запускает вашу работу в пуле за кулисами.Его цель - просто отслеживать фоновые задачи, которые в данный момент выполняются, чтобы ASP.NET мог дождаться их завершения, прежде чем перезапускать домен приложения (что может произойти, например, при внесении изменений в файл web.config).Кроме того, чтобы использовать HostingEnvironment
, вам нужна ссылка на System.Web.dll
, так что это не помощник, который вы должны использовать, например, для консольного приложения.
Тем не менее, скажем, что это действительно то, что вам нужносделать.Первая проблема в вашем коде заключается в том, что вы звоните .Result
. Это вызовет истощение пула потоков.Вместо этого дождитесь выполнения задачи (кроме того, вы всегда должны использовать Task.Run
, если у вас нет веских оснований для использования Task.Factory.StartNew
. Если вы не знаете, каковы эти причины, это признак того, что вы должны определенно используйте Task.Run
вместо).
Вторая проблема: как ждать, когда элемент запланирован в HostingEnvironment?Для этого вы должны использовать TaskCompletionSource
.Ваш код будет выглядеть так:
private static Task<T> GetTask<T>(Func<T> valueFactory)
{
if (HostingEnvironment.IsHosted)
{
var tcs = new TaskCompletionSource<T>(TaskCreationOptions.RunContinuationsAsynchronously);
HostingEnvironment.QueueBackgroundWorkItem(_ =>
{
tcs.SetResult(valueFactory());
});
return tcs.Task;
}
return Task.Run(valueFactory);
}