2015-03-13 8 views
8

Я переключается на Task.Run на Hangfire. В .NET 4.5+ Task.Run может возвращаться Task<TResult>, что позволяет мне запускать задачи, которые возвращаются за исключением void. Я могу нормально подождать и получить результат моей задачи путем доступа к свойству MyReturnedTask.ResultРабота в фоновом режиме с возвращаемым значением

Примера моего старого кода:

public void MyMainCode() 
{ 
    List<string> listStr = new List<string>(); 
    listStr.Add("Bob"); 
    listStr.Add("Kate"); 
    listStr.Add("Yaz"); 

    List<Task<string>> listTasks = new List<Task<string>>(); 

    foreach(string str in listStr) 
    { 
     Task<string> returnedTask = Task.Run(() => GetMyString(str)); 
     listTasks.Add(returnedTask); 
    } 

    foreach(Task<string> task in listTasks) 
    { 
     // using task.Result will cause the code to wait for the task if not yet finished. 
     // Alternatively, you can use Task.WaitAll(listTasks.ToArray()) to wait for all tasks in the list to finish. 
     MyTextBox.Text += task.Result + Environment.NewLine; 
    } 
} 
private string GetMyString(string str) 
{ 
    // long execution in order to calculate the returned string 
    return str + "_finished"; 
} 

Насколько я могу видеть из Quick Start страницы замедленного воспламенения, ваш главный парня, который BackgroundJob.Enqueue(() => Console.WriteLine("Fire-and-forget")); отлично выполняет код как фоновое задание, но, по-видимому, не поддерживает задания, которые имеют возвращаемое значение (например, код, представленный выше). Это правильно? если нет, как я могу настроить мой код, чтобы использовать Hangfire?

P.S. Я уже смотрел на HostingEnvironment.QueueBackgroundWorkItem (here), но по-видимому, не имеет такую ​​же функциональность (фоновые задания должны быть void)

EDIT

Как @Dejan выяснил, главная причина, я хочу, чтобы переключиться на замедленное воспламенение является по той же причине пользователи .NET добавили QueueBackgroundWorkItem в .NET 4.5.2. И эта причина хорошо охарактеризована в замечательном article Скотта Хансельмана о Фоновых Задачах в ASP.NET. Так что я собираюсь цитата из статьи:

QBWI (QueueBackgroundWorkItem) графики задачу, которая может работать в фоновом режиме, независимо от любого запроса. Это отличается от обычного рабочего элемента ThreadPool тем, что ASP.NET автоматически отслеживает, сколько рабочих элементов зарегистрировано через этот API в настоящее время запущено, а время выполнения ASP.NET будет попытаться отложить закрытие AppDomain до завершения этих рабочих элементов выполнение.

+2

Возвращаемое значение методов отображается на странице информации о задании на панели управления. Если вы посмотрите в соответствующей таблице db для заданий Hangfire, возвращаемое значение должно быть сохранено в поле. См. Https://github.com/HangfireIO/Hangfire/pull/161 - кроме этого я не знаю, доступно ли ему доступ к нему программно – adaam

+0

Спасибо, что указали это. – yazanpro

+0

У меня точно такой же вопрос. Вы что-то задумали? – Dejan

ответ

7

Одно простое решение будет опрашивать API мониторинга до тех пор, пока работа не будет закончена, как это:

public static Task Enqueue(Expression<Action> methodCall) 
    { 
     string jobId = BackgroundJob.Enqueue(methodCall); 
     Task checkJobState = Task.Factory.StartNew(() => 
     { 
      while (true) 
      { 
       IMonitoringApi monitoringApi = JobStorage.Current.GetMonitoringApi(); 
       JobDetailsDto jobDetails = monitoringApi.JobDetails(jobId); 
       string currentState = jobDetails.History[0].StateName; 
       if (currentState != "Enqueued" && currentState != "Processing") 
       { 
        break; 
       } 
       Thread.Sleep(100); // adjust to a coarse enough value for your scenario 
      } 
     }); 
     return checkJobState; 
    } 

Внимание: Конечно, в веб-принимал сценарии вы не можете рассчитывать на продолжение задача (task.ContinueWith()) сделать больше вещей после завершения работы, поскольку AppDomain может быть закрыт - по тем же причинам вы, вероятно, захотите использовать Hangfire в первую очередь.

+0

Спасибо, и последняя фраза о причине, по которой я перехожу на Hangfire, абсолютно прав. – yazanpro

+0

Дело в том, что не может быть пуленепробиваемого решения, которое включает в себя возвращение Задачи. – Dejan

+0

Я использовал тот же код, но все же он несколько раз проваливался и проходил большую часть времени. Я пробовал с добавлением проверки «Ожидание», и теперь он работает даже без Thread.Sleep. if (currentState! = "Enquued" && currentState! = "Обработка" && currentState! = "Ожидание") –