我在ASP.NET MVC项目(产品应用)中有一个操作方法,该方法可以导入csv文件记录并在进度条上显示进度,为此我使用了https://stackoverflow.com/a/2928148/1386991,这对于全新的MVC项目效果很好(POC应用)。
但是,当我在原始项目(产品应用)中放置完全相同的控制器并查看(带有js代码)时,CheckTaskProgress
方法仅在RunLongTask
完成任务时才会命中,因此用户看不到进度条更新并突然发生100%的变化,这与我在全新项目(POC应用程序)中的行为完全相反。这是可见的行为屏幕截图,供您参考https://www.youtube.com/watch?v=wNa5De0lmdA。
我检查了MVC软件包的版本和web.config,看起来不错。有任何检查线索吗?
这是控制器代码:
using System;
using System.Web.Mvc;
using System.Threading.Tasks;
namespace Prod.Web.Controllers
{
public class DemoController : Controller
{
public ActionResult Index()
{
return View();
}
[HttpPost]
public async Task<ActionResult> RunLongTask()
{
string id = "task_id1"; //should be unique
int maxcount = 200;
AsyncManager.OutstandingOperations.Increment();
await Task.Factory.StartNew(taskId =>
{
HttpContext.Application["t_max_" + taskId] = maxcount;
for (int i = 0; i < maxcount; i++)
{
System.Threading.Thread.Sleep(100);
HttpContext.Application["t_prog_" + taskId] = i;
}
AsyncManager.OutstandingOperations.Decrement();
}, id);
return Json(new { status = true, ProgressCurrent = maxcount, ProgressMax = maxcount, ProgressPercent = 100 });
}
public ActionResult CheckTaskProgress()
{
string id = "task_id1"; //should be unique
var progressCurrent = HttpContext.Application["t_prog_" + id];
var progressMax = HttpContext.Application["t_max_" + id];
decimal progressPercent = (Convert.ToDecimal(progressCurrent) / Convert.ToDecimal(progressMax)) * 100M;
return Json(new
{
ProgressCurrent = progressCurrent,
ProgressMax = progressMax,
ProgressPercent = Convert.ToInt32(progressPercent)
}, JsonRequestBehavior.AllowGet);
}
}
}
这是js代码的视图:
@{
ViewBag.Title = "Run ajax long running process and display on progress bar";
}
<div class="main-wrap">
<div class="container">
<div class="row py-5">
<div class="col-12">
<button class="btn btn-primary runlongtask">
<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true" style="display:none;"></span>
Run ajax long running process and display on progress bar
</button>
</div>
<div class="col-12 pt-5">
<div class="progress">
<div class="progress-bar" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="0" style="width:0%"></div>
</div>
</div>
</div>
</div>
</div>
@section foot{
<script>
$(function () {
$('.runlongtask').click(function () {
var triggerbtn = $(this);
triggerbtn.prop('disabled', true).children('.spinner-border').show();
$.ajax({
type: 'POST',
url: '/demo/runlongtask',
success: function (data) {
if (data.status) {
longTaskUpdateProgress(data.ProgressCurrent, data.ProgressMax, data.ProgressPercent);
triggerbtn.prop('disabled', false).children('.spinner-border').hide();
window.clearInterval(longTaskInterval);
}
}
});
var longTaskInterval = window.setInterval(function () {
console.log('interval func invoked');
$.ajax({
type: 'GET',
url: '/demo/checktaskprogress',
success: function (data) {
longTaskUpdateProgress(data.ProgressCurrent, data.ProgressMax, data.ProgressPercent);
}
});
}, 5000);
var longTaskUpdateProgress = function (ProgressCurrent, ProgressMax, ProgressPercent) {
console.log('progressbar func invoked');
$('.progress-bar')
.attr('aria-valuenow', ProgressPercent)
.css('width', ProgressPercent + '%')
.html(ProgressPercent + '% Completed');
console.log(ProgressPercent + ' Completed');
console.log(ProgressCurrent + ' executed out of ' + ProgressMax);
};
});
})
</script>
}
这是我在GitHub https://github.com/itorian/Run-Ajax-Long-Process-With-Progress-Bar上的项目(POC应用程序)的源代码。
答案 0 :(得分:3)
有两种可能:
CheckTaskProgress
调用将一直阻塞,直到RunLongTask
完成,因为它正在等待会话可用。async
/await
。在这种情况下,您应该添加一个适当的httpRuntime
targetFramework
值。旁注:
StartNew
。我什至不确定为什么它在原始代码中。无需进行StartNew
和AsyncManager
调用,它应该可以正常工作。答案 1 :(得分:1)
不建议将异步代码和非异步(阻止)代码混合使用,因此以下语句将引起问题:
=SUBSTITUTE(CONCATENATE(D1,">",E1,">",F1,">",G1,">",H1), ">>", ">")
替换为:
System.Threading.Thread.Sleep(100);
经验法则是一直向下同步