Dan*_*man 5 asp.net-mvc jquery progress-bar
我正在努力取得进步.在服务器端,我创建了一个控制器,它应该获取进度值并将值存储在会话中.
在客户端,我创建了两个ajax请求.其中一个启动一个函数,我想监视它,另一个只是检查进度阶段.我的意思是,这就是我认为它会起作用的方式.但它只会在完成后输出一些东西.
它只是等待几秒钟然后警告"完成!" 就这样.
有什么问题?也许我应该在控制器中创建新线程来监控进度阶段?
这是客户端代码:
function generate() {
setTimeout(checkProgress, 400);
$.ajax({
type: "POST",
url: "/PPTReport/Generate",
async: true,
success: function (text) {
console.log(text);
},
error:function() {
console.log("error! error!");
}
});
}
function checkProgress() {
var id = "reportProgress";
$.ajax({
type: "POST",
url: "/PPTReport/GetProgress",
async: true,
data: "id="+id,
success: function (data) {
if (data.done) {
console.log('Done!');
} else {
console.log('Progress at ' + data.percent + '%');
console.log(data.percent);
setTimeout(checkProgress, 100 );
}
},
error: function() {
console.log('ajax error');
}
});
}
Run Code Online (Sandbox Code Playgroud)
这是服务器端代码
public class ProgressInfo
{
public int Percent { get; set; }
public bool Done { get; set; }
}
public JsonResult GetProgress(string id)
{
ProgressInfo progress;
if (string.IsNullOrEmpty(id)
|| (progress = Session[id] as ProgressInfo) == null)
{
return Json(new
{
success = false
});
}
if (progress.Done)
{
Session.Remove(id);
}
return Json(new
{
success = true,
done = progress.Done,
percent = progress.Percent
}
);
}
public JsonResult Generate(){
//init stuff
//there are somtheing like that
ProgressInfo progress = new ProgressInfo();
progress.Percent = 0;
progress.Done = false;
if (tabs > 0)
{
FirstPage();
progress.Percent++;
Session["reportProgress"] = progress;
if (tabs > 1)
{
SecondPage();
progress.Percent++;
Session["reportProgress"] = progress;
if (tabs > 2)
{
ThirdPage();
progress.Percent++;
Session["reportProgress"] = progress;
if (tabs > 3)
{
LastPage();
}
}
}
}
//what we've gonna return stuff etc
}
Run Code Online (Sandbox Code Playgroud)
UPD:嗯,我终于有点了 - 我做了测试功能(几乎就像在例子中)这是代码:
JS:
function doCalculation() {
$.post('/PPTReport/DoCalculation/sas');
setTimeout(pollProgress, 1000);
}
function pollProgress() {
var progressID = "sas";
$.post('/PPTReport/GetProgress/' + progressID, function (response) {
if (!response.success) {
alert('Cannot find progress');
return;
}
if (response.done) {
alert('Done!');
} else {
alert('Progress at ' + response.percent + '%');
setTimeout(pollProgress, 1000);
}
}, 'json');
Run Code Online (Sandbox Code Playgroud)
}
服务器端:
public void DoCalculation(string id)
{
ProgressInfo progress = new ProgressInfo();
if (!string.IsNullOrEmpty(id))
{
Session[id] = progress;
}
//periodicly update progress
int i = 0;
while(i == 0 && progress.Percent != 7600000340)
{
progress.Percent++;
Thread.Sleep(1000);
}
}
public JsonResult GetProgress(string id)
{
ProgressInfo progress;
if (string.IsNullOrEmpty(id)
|| (progress = Session[id] as ProgressInfo) == null)
{
return Json(new
{
success = false
});
}
if (progress.Done)
{
Session.Remove(id);
}
return Json(new
{
success = true,
done = progress.Done,
percent = progress.Percent
});
}
Run Code Online (Sandbox Code Playgroud)
但我等了一分多钟,直到行动第一次执行!
看

为什么会这样?它只是调用简单的函数,为什么它等待这么久?
小智 7
这是一个老问题的实例,请看这里:
http://msdn.microsoft.com/en-us/library/ms178581.aspx
对会话状态的访问是每个会话独占的,这意味着如果两个不同的用户发出并发请求,则同时授予对每个单独会话的访问权限.但是,如果对同一会话发出两个并发请求(通过使用相同的SessionID值),则第一个请求将获得对会话信息的独占访问权.第二个请求仅在第一个请求完成后执行.(如果由于第一个请求超过锁定超时而释放信息的独占锁定,则第二个会话也可以访问.)如果@ Page指令中的EnableSessionState值设置为ReadOnly,则只读请求会话信息不会导致会话数据的独占锁定.但是,会话数据的只读请求可能仍然必须等待由会话数据的读写请求设置的锁定才能清除.
我想你可以在SO上找到很多关于这个问题的帖子.这是一个:
异步控制器通过jQuery阻止ASP.NET MVC中的请求
这是一个解决方法:
好的,添加一些(未经测试的!)示例代码.这只是为了说明如何解决这个问题:
public class myCache {
private static Dictionary<string, ProgressInfo> _pinfos = new Dictionary<string, ProgressInfo>();
private static readonly object _lockObject = new object();
public static void Add(string key, ProgressInfo value)
{
lock (_lockObject)
{
if (!_pinfos.ContainsKey(key)) {
_pinfos.Add(key, value);
}
else {
_pinfos[key] = value;
}
}
}
public static ProgressInfo Get(string key) {
if (_pinfos.ContainsKey(key)) {
return _pinfos[key];
}
else {
return null;
}
}
public static void Remove(string key) {
lock (_lockObject)
{
if (_pinfos.ContainsKey(key)) {
_pinfos.Remove(key);
}
}
}
}
[SessionState(SessionStateBehavior.ReadOnly)]
public class TestController : AsyncController
public void DoCalculation(string id)
{
ProgressInfo progress = new ProgressInfo();
if (!string.IsNullOrEmpty(id)) {
myCache.Add(id,progress);
}
//periodicly update progress
int i = 0;
while(i == 0 && progress.Percent != 7600000340)
{
progress.Percent++;
Thread.Sleep(1000);
}
}
public JsonResult GetProgress(string id)
{
ProgressInfo progress;
if (string.IsNullOrEmpty(id)
|| (progress = myCache.Get(id)) == null)
{
return Json(new
{
success = false
});
}
if (progress.Done)
{
myCache.Remove(id);
}
return Json(new
{
success = true,
done = progress.Done,
percent = progress.Percent
});
}
}
Run Code Online (Sandbox Code Playgroud)