私のWebApiアプリケーションでは、次のトピックのようなことを行う必要があります。ASP.NetWebアプリでバックグラウンドタスクを実行し、フィードバックを取得するための最良の方法は?アプリケーションでは、ユーザーはExcelファイルをアップロードしてから、そのデータをデータベース内のテーブルにインポートできます。すべて正常に機能しますが、インポートプロセスには長い時間がかかる可能性があり(Excelに行が多い場合は、約20分)、プロセスが開始されるとページがブロックされ、ユーザーはこの間ずっと待つ必要があります。このインポートプロセスをバックグラウンドで実行する必要があります。
私はこのPOSTメソッドを備えたコントローラーを持っています:
[HttpPost]
public async Task<IHttpActionResult> ImportFile(int procId, int fileId)
{
string importErrorMessage = String.Empty;
// Get excel file and read it
string path = FilePath(fileId);
DataTable table = GetTable(path);
// Add record for start process in table Logs
using (var transaction = db.Database.BeginTransaction()))
{
try
{
db.uspAddLog(fileId, "Process Started", "The process is started");
transaction.Commit();
}
catch (Exception e)
{
transaction.Rollback();
importErrorMessage = e.Message;
return BadRequest(importErrorMessage);
}
}
//Using myHelper start a store procedure, which import data from excel file
//The procedure also add record in table Logs when it is finished
using (myHelper helper = new myHelper())
helper.StartImport(procId, fileId, table, ref importErrorMessage);
if (!String.IsNullOrEmpty(importErrorMessage))
return BadRequest(importErrorMessage);
return Ok(true);
}
ファイルとそのプロセスに関する情報を返すGETメソッドもあります
[HttpGet]
[ResponseType(typeof(FileDTO))]
public IQueryable<FileDTO> GetFiles(int procId)
{
return db.LeadProcessControl.Where(a => a.ProcessID == procId)
.Project().To<FileDTO>();
}
次のようなJSONを返します。
{
FileName = name.xlsx
FileID = 23
ProcessID = 11
Status = Started
}
この方法はGRID用です
File name | Status | Button to run import | Button to delete file
これStatus
はテーブルLogs
からのものでFileDTO
あり、最後の値が配置されています。たとえば、ファイルをアップロードすると、status
インポートを実行すると「ファイルがアップロードされました」になり、インポートstatus
が終了status
すると「完了」になります。ただし、インポートプロセスの実行中にページがロックされるようになったため、ステータスは常に「完了」になります。
したがって、プロシージャをバックグラウンドで実行する必要があり、Status
変更されている場合はGETメソッドがnewを返す必要があります。助言がありますか?
メソッドにasyncを追加しても、メソッド呼び出しは非同期になりません。これは、現在の要求を処理しているスレッドが、ネットワーク/ディスクIOを待機している間に、他の要求を処理するために再利用できることを示しているだけです。クライアントがこのメソッドを呼び出すと、メソッドが完了したときにのみ応答が返されます。言い換えれば、非同期は完全にサーバー側のものであり、クライアント呼び出しとは何の関係もありません。以下に示すように、長時間実行されるプロセスを別のスレッドで開始する必要があります。ただし、ベストプラクティスは、このような長時間実行される処理にWebアプリを使用せず、代わりに別のWindowsサービスで長時間処理を実行することです。
[HttpPost]
public async Task<IHttpActionResult> ImportFile(int procId, int fileId)
{
string importErrorMessage = String.Empty;
// Get excel file and read it
string path = FilePath(fileId);
DataTable table = GetTable(path);
// Add record for start process in table Logs
using (var transaction = db.Database.BeginTransaction()))
{
try
{
db.uspAddLog(fileId, "Process Started", "The process is started");
transaction.Commit();
}
catch (Exception e)
{
transaction.Rollback();
importErrorMessage = e.Message;
return BadRequest(importErrorMessage);
}
}
//Start long running process in new thread
Task.Factory.StartNew(()=>{
using (myHelper helper = new myHelper())
{
helper.StartImport(procId, fileId, table, ref importErrorMessage);
//** As this code is running background thread you cannot return anything here. You just need to store status in database.
//if (!String.IsNullOrEmpty(importErrorMessage))
//return BadRequest(importErrorMessage);
}
});
//You always return ok to indicate background process started
return Ok(true);
}
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加