2015-03-13 19 views
8

Task.Run'dan Hangfire'a geçiyorum. .NET 4.5+ Task.Run içinde Task<TResult> dönebilir, bu da void dışında dönen görevleri çalıştırmamı sağlar. Normalde bekleyip özellik zaman eski kod MyReturnedTask.ResultGeri Dönüş Değeri ile Hangfire Arkaplan İşi

Örnek erişerek Görevimin sonucu alabilirsiniz:, ana adamı ben Hangfire ait Quick Start sayfasından görebilirsiniz kadarıyla

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"; 
} 

hangi BackgroundJob.Enqueue(() => Console.WriteLine("Fire-and-forget")); , kodu bir arka plan işi olarak mükemmel şekilde çalıştırır, ancak dönüş değeri olan işleri desteklemiyor (yukarıda belirttiğim kod gibi). Bu doğru mu? değilse, Hangfire'ı kullanmak için kodumu nasıl değiştirebilirim?

P.S. @Dejan anladım gibi

, ben Hangfire geçmek istediğiniz ana nedeni

olan DÜZENLEME (arka plan işleri void olmak zorunda) Zaten HostingEnvironment.QueueBackgroundWorkItem (here) baktı ama görünüşte aynı işlevi olmaması .NET'in aynı nedeni, .NET 4.5.2'de QueueBackgroundWorkItem ekledi. Ve bu sebep, Scott Hanselman'ın ASP.NET'teki Arka Plan Görevleri hakkındaki harika article'da iyi tanımlanmıştır.

QBWI (QueueBackgroundWorkItem) programları arka planda çalışabilir bir görev, herhangi istek bağımsız: Ben makaleden olacak alıntı değilim. Bu, içinde bulunan normal bir ThreadPool iş öğesinden farklıdır. ASP.NET, bu API aracılığıyla kayıtlı kaç çalışma öğesinin şu anda çalıştığını otomatik olarak izler ve ASP.NET çalışma zamanı, , bu iş öğeleri bitene kadar AppDomain kapatma işlemini geciktirmeyi deneyecektir yürütme.

+2

Yöntemlerin dönüş değeri, İşin Kontrol Paneli'ndeki bilgi sayfasında görüntülenir. Hangfire işleri için ilgili db tablosuna bakarsanız, dönüş değeri oradaki bir alanda saklanmalıdır. Https://github.com/HangfireIO/Hangfire/pull/161 bakın - yanı sıra programatik – adaam

+0

erişmek için olanaklı olup olmadığından emin değilim. – yazanpro

+0

Tam olarak aynı soruyu yaşıyorum. Bu arada bir şey buldun mu? – Dejan

cevap

7

iş böyle tamamlanana kadar basit bir çözüm izleme API yoklamaya olacaktır:

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; 
    } 

Dikkat: Tabii, web'de barındırılan senaryosunda size devamında güvenemez Görev tamamlandıktan sonra (task.ContinueWith()), AppDomain kapandığında işin bitmesiyle ilgili daha fazla şey yapmak için - aynı nedenlerden dolayı Hangfire'ı ilk etapta kullanmak isteyebilirsiniz.

+0

Teşekkür ederim, Hangfire'a geçmemin sebebi ile ilgili son söz tamamen haklı. – yazanpro

+0

Önemli olan, bir Görev döndürmeyi içeren kurşun geçirmez bir çözüm olamaz. – Dejan

+0

Aynı kodu kullandım ama yine de birkaç kez başarısız oldu ve çoğu zaman geçti. "Bekliyor" kontrolünü eklemeye çalıştım ve şimdi Thread.Sleep olmadan bile çalışıyor. if (currentState! = "Enqueued" && currentState! = "Processing" && currentState! = "Bekleniyor") –

İlgili konular