.NETコアWeb APIを使用しており、さまざまな強度の要求をデータベースに記録するための軽量なソリューションを探していますが、クライアントに保存プロセスを待たせたくありません。
dnx
にはHostingEnvironment.QueueBackgroundWorkItem(..)
が実装されておらず、Task.Run(..)
は安全ではありません。
優雅なソリューションはありますか?.NETコアのHostingEnvironment.QueueBackgroundWorkItemの代替ソリューション
答えて
.NET Coreのバックグラウンドジョブには、Hangfire(http://hangfire.io/)を使用できます。例えば
:
var jobId = BackgroundJob.Enqueue(
() => Console.WriteLine("Fire-and-forget!"));
QueueBackgroundWorkItem
がなくなっていますが、我々は前者によって使用されている代わりにIRegisteredObject
のIApplicationLifetime
を、持っています。そして、このようなシナリオではかなり有望です。
アイデア(と私はまだそれはかなり悪いので、確信していないので、注意!)は、を生成し、が新しいタスクを遵守するシングルトンを登録することです。そのシングルトン内では、まだ実行中のタスクを適切に待つために、「停止イベント」を登録することができます。
この「概念」は、ロギング、メール送信などの短時間実行のものに使用できます。ものすごく時間がかかりませんが、現在のリクエストに対して不必要な遅延が発生します。
public class BackgroundPool
{
protected ILogger<BackgroundPool> Logger { get; }
public BackgroundPool(ILogger<BackgroundPool> logger, IApplicationLifetime lifetime)
{
if (logger == null)
throw new ArgumentNullException(nameof(logger));
if (lifetime == null)
throw new ArgumentNullException(nameof(lifetime));
lifetime.ApplicationStopped.Register(() =>
{
lock (currentTasksLock)
{
Task.WaitAll(currentTasks.ToArray());
}
logger.LogInformation(BackgroundEvents.Close, "Background pool closed.");
});
Logger = logger;
}
private readonly object currentTasksLock = new object();
private readonly List<Task> currentTasks = new List<Task>();
public void SendStuff(Stuff whatever)
{
var task = Task.Run(async() =>
{
Logger.LogInformation(BackgroundEvents.Send, "Sending stuff...");
try
{
// do THE stuff
Logger.LogInformation(BackgroundEvents.SendDone, "Send stuff returns.");
}
catch (Exception ex)
{
Logger.LogError(BackgroundEvents.SendFail, ex, "Send stuff failed.");
}
});
lock (currentTasksLock)
{
currentTasks.Add(task);
currentTasks.RemoveAll(t => t.IsCompleted);
}
}
}
ようなBackgroundPool
はシングルトンとして登録されるべきであるとDIを介して他のコンポーネントによって使用されることができます。私は現在、メールを送信するためにそれを使用しています。
注:背景のタスク内の現在のHttpContext
のようなものにアクセスすることはできません。 old solutionは、とにかく禁止するためにUnsafeQueueUserWorkItem
を使用します。
あなたはどう思いますか?
更新:ASP.NETコアと
が2.0新しいものは、ASP.NETコア2.1とのより良いの取得のバックグラウンドタスクにあります:Implementing background tasks in .NET Core 2.x webapps or microservices with IHostedService and the BackgroundService class
ここであなたをすることができますAxel's answerの微調整バージョンです代理人を渡し、完了したタスクのより積極的なクリーンアップを行います。
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Logging;
namespace Example
{
public class BackgroundPool
{
private readonly ILogger<BackgroundPool> _logger;
private readonly IApplicationLifetime _lifetime;
private readonly object _currentTasksLock = new object();
private readonly List<Task> _currentTasks = new List<Task>();
public BackgroundPool(ILogger<BackgroundPool> logger, IApplicationLifetime lifetime)
{
if (logger == null)
throw new ArgumentNullException(nameof(logger));
if (lifetime == null)
throw new ArgumentNullException(nameof(lifetime));
_logger = logger;
_lifetime = lifetime;
_lifetime.ApplicationStopped.Register(() =>
{
lock (_currentTasksLock)
{
Task.WaitAll(_currentTasks.ToArray());
}
_logger.LogInformation("Background pool closed.");
});
}
public void QueueBackgroundWork(Action action)
{
#pragma warning disable 1998
async Task Wrapper() => action();
#pragma warning restore 1998
QueueBackgroundWork(Wrapper);
}
public void QueueBackgroundWork(Func<Task> func)
{
var task = Task.Run(async() =>
{
_logger.LogTrace("Queuing background work.");
try
{
await func();
_logger.LogTrace("Background work returns.");
}
catch (Exception ex)
{
_logger.LogError(ex.HResult, ex, "Background work failed.");
}
}, _lifetime.ApplicationStopped);
lock (_currentTasksLock)
{
_currentTasks.Add(task);
}
task.ContinueWith(CleanupOnComplete, _lifetime.ApplicationStopping);
}
private void CleanupOnComplete(Task oldTask)
{
lock (_currentTasksLock)
{
_currentTasks.Remove(oldTask);
}
}
}
}
Axelの答えのように、実際には "Task.WaitAll(currentTask.ToArray());"から返されたタスクを待つことはありません。 – Shazi
@axelheerはIHostedServiceを述べたように、.NETのコア2.0以上で移動するための方法です。
私はHostingEnvironment.QueueBackgroundWorkItemのようなASP.NET Core Replacementのような軽量が必要でしたので、.NETコアの2.0 IHostedServiceを使用するDalSoft.Hosting.BackgroundQueueを書きました。
PM>インストール・パッケージのごASP.NETコアスタートアップでDalSoft.Hosting.BackgroundQueue
を。CS:
public void ConfigureServices(IServiceCollection services)
{
services.AddBackgroundQueue(onException:exception =>
{
});
}
ちょうどあなたのコントローラのコンストラクタにBackgroundQueue
を追加し、Enqueue
を呼び出して、バックグラウンドタスクをキューに。
public EmailController(BackgroundQueue backgroundQueue)
{
_backgroundQueue = backgroundQueue;
}
[HttpPost, Route("/")]
public IActionResult SendEmail([FromBody]emailRequest)
{
_backgroundQueue.Enqueue(async cancellationToken =>
{
await _smtp.SendMailAsync(emailRequest.From, emailRequest.To, request.Body);
});
return Ok();
}
- 1. EmitCalli .NETコア代替
- 2. .NETコアのSignedCms代替語
- 3. NS代替ILogger .NETコア
- 4. .NETでのThread.Sleepの代替機能コア
- 5. ASPのhtaccessの代替ソリューション
- 6. Microsoft.ACE.OLEDB.12.0プロバイダの代替ソリューション
- 7. WebHostBuilder.Build().NETコア移行ソリューションのMissingMethodException
- 8. SQLのwhileループの代替ソリューション
- 9. PostgreSQLの機能TEMP TABLEの代替ソリューション
- 10. .netのApache camelの代替?
- 11. Prototype JSハッシュテーブルJqueryの代替案/ソリューション
- 12. オブジェクトフィットの代替ソリューション? (AngularJS&ng-repeat)
- 13. QueryWithRowMapperDelegateパフォーマンスの問題 - 代替ソリューション
- 14. RSAセキュリティIDの代替ソリューションID
- 15. iframeの代替ソリューションですか?
- 16. Android O:ブロードキャストの制限PHONE_STATE代替ソリューション
- 17. .Net CoreのCERTENROLLLib代替語
- 18. ASP .NETの代替リダイレクト
- 19. NTFS代替データストリーム - .NET
- 20. 代替WebBrowser .Net C#
- 21. dotnetコア用のString.Copyの代替ファイル
- 22. .NETコアのUTF8Encodingクラスの代わりに
- 23. System.Web.Hosting.HostingEnvironment.RegisterObject for asp.netコア2.0の代替
- 24. .netコアの代わりにFtpWebRequest
- 25. C++:テンプレートに対する代替ソリューション
- 26. C#クロスプラットフォームRichTextBox URLまたは代替ソリューション
- 27. .NET列挙継承代替
- 28. asp net imagebutton代替テキストmultiline
- 29. .NET 3.5のGetGlobalAsaxTypeの代替ですか?
- 30. グローバルスコープ内の.NETセッションの代替
なぜダウン票ですか?私には非常に良い質問のように見えます。 QueueBackgroundWorkItemは確かに非常に便利です。 –
'HostingEnvironment.QueueBackgroundWorkItem'も安全ではありませんでした。 'Task.Run'よりも安全性は低くなりましたが、安全ではありませんでした。 –
良い質問です。私はsignalR進行報告者(IProgressインタフェースを使用して)を実装しようとしていますが、SignalRの非同期性のために、報告している操作を遅らせることなく、タスクとして(非常に短命ですが)進捗報告を処理する必要があります。 – Shazi