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";
}
_
Hangfireの Quick Start ページからわかる限り、BackgroundJob.Enqueue(() => Console.WriteLine("Fire-and-forget"));
であるメインの人は、バックグラウンドジョブとしてコードを完全に実行しますが、次のようなジョブをサポートしていないようです。戻り値(上記のコードのように)。そうですか?そうでない場合、Hangfireを使用するためにコードを微調整するにはどうすればよいですか?
P.S.私はすでに_HostingEnvironment.QueueBackgroundWorkItem
_( ここ )を見ましたが、明らかに同じ機能が欠けています(バックグラウンドジョブはvoid
でなければなりません)
[〜#〜]編集[〜#〜]
@Dejanが理解したように、私がHangfireに切り替えたい主な理由は、.NETの人々が.NET4.5.2にQueueBackgroundWorkItem
を追加したのと同じ理由です。そして、その理由は、ASP.NETのバックグラウンドタスクに関するScott Hanselmanのすばらしい 記事 に詳しく説明されています。だから私は記事から引用するつもりです:
QBWI(QueueBackgroundWorkItem)は、リクエストに関係なく、バックグラウンドで実行できるタスクをスケジュールします。これは通常のThreadPool作業項目とは異なり、ASP.NETはこのAPIを介して登録された作業項目の数を自動的に追跡し、ASP.NETランタイムはこれらの作業項目の実行が完了するまでAppDomainのシャットダウンを遅らせようとします。
簡単な解決策の1つは、次のようにジョブが終了するまで監視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;
}
_
注意:もちろん、Webでホストされるシナリオでは、AppDomainがシャットダウンされる可能性があるため、ジョブの終了後にタスク(task.ContinueWith()
)の継続に依存してさらに多くのことを実行することはできません。ダウン-同じ理由で、おそらく最初にHangfireを使用したいと思うでしょう。