我正在尝试取得进度栏。在服务器端,我创建了一个控制器,该控制器应获取进度值并将其存储在会话中。
在客户端,我创建了两个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');
}
});
}
这是服务器端代码
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
}
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');
}
服务器端:
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
});
}
但我等了超过一分钟,才第一次执行该操作!看
为什么会发生?它只是调用简单函数,为什么要等待这么长时间?
这是一个旧问题的实例,请参见此处:
http://msdn.microsoft.com/en-us/library/ms178581.aspx
对ASP.NET会话状态的访问是每个会话的独占,这意味着如果两个不同的用户发出并发请求,则将同时授予对每个单独会话的访问权限。但是,如果对同一会话提出了两个并发请求(通过使用相同的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
});
}
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句