我已经搜索了几天,并尝试了我能找到的所有解决方案。我知道这是我做得不好的事情,但是,我不确定正确的方法是什么。
我有一个ASP.Net C#网站,在.Net Framework 4.5上运行。我在表单上有一个链接按钮,单击该按钮时会使用ThreadPool触发长时间运行的进程。我有一个委托回调设置,代码在取消进程或完成时触发。 (我使用取消令牌取消流程,如果重要的话,流程是活动报告。)
就像我说的,一切都很好,除了当回调代码触发它不执行javascript时。 (仅供参考 - 这不是一个javascript回调,只是尝试在进程完成时触发一些javascript代码。)
string sThreadID = Thread.CurrentThread.ManagedThreadId.ToString(); ThreadPool.QueueUserWorkItem(new WaitCallback(StartReport),cts.Token);
public static void StartReport(object obj) {
try {
OnTaskCompleteDelegate callback = new OnTaskCompleteDelegate(OnTaskComplete);
BoyceReporting.CallReport(boyce.BoyceThreadingEnvironment.OBRO, "THREADING");
if (boyce.BoyceThreadingEnvironment.CTS.Token.IsCancellationRequested) {
boyce.BoyceThreadingEnvironment.SESSION.sScriptToExecute = "alert('Report Canceled By User');";
callback("CANCELED");
} else {
callback("FINISHED");
}
} catch {
throw;
}
}
public static void OnTaskComplete(string ReportResult) {
try {
sReportResult = ReportResult;
if (ReportResult == "CANCELED") {
// In case we need to do additional things if the report is canceled
}
string sThreadID = Thread.CurrentThread.ManagedThreadId.ToString();
boyce.BoyceThreadingEnvironment.THISPAGE.ClientScript.RegisterStartupScript(boyce.BoyceThreadingEnvironment.THISPAGE.GetType(), "FireTheScript" + DateTime.Now.ToString(), boyce.BoyceThreadingEnvironment.SESSION.sScriptToExecute, true);
ScriptManager.RegisterStartupScript(boyce.BoyceThreadingEnvironment.THISPAGE, boyce.BoyceThreadingEnvironment.THISPAGE.GetType(), "DisplayReport" + DateTime.Now.ToString(), boyce.BoyceThreadingEnvironment.SESSION.sScriptToExecute, true);
} catch {
throw;
}
}
一切正常,但我无法获取最后一行代码来解雇脚本。 ScriptManager.RegisterStartupScript
从查看线程ID,我确定代码未触发的原因是因为我试图在Call Back事件中触发的ScriptManager代码位于不同于主线程的线程上。
(1)我是否正确解释了为什么这不会触发JavaScript (2)我如何(从CallBack内部)获取此JavaScript?有没有办法强制它在主线程上执行?
答案 0 :(得分:1)
它没有在JS中解雇,因为你正在关闭一个新线程。与此同时,请求早已返回到客户端并关闭连接。当线程试图向Response写出一些内容时,它已经完成了。
而不是这样做,只需按一下UpdatePanel
按钮点击(或启动报告的任何内容)。然后,您不需要启动新线程。
答案 1 :(得分:0)
Here is the cod I used in the C# Code Behind to call the web service to start monitoring this process.
----------------------------------------------------------------------------------------------
CurrentSession.bIsReportRunning = true;
ScriptManager.RegisterStartupScript(this, this.GetType(), "WaitForReport" + DateTime.Now.ToString(), "jsWaitOnCallReport();", true);
MultiThreadReport.RunTheReport(HttpContext.Current, CurrentSession, this, oBRO);
Here is the code that calls the method, using the threadpool, and the method called..
----------------------------------------------------------------------------------------------
ThreadPool.QueueUserWorkItem(new WaitCallback(StartReport), cts.Token);
public static void StartReport(object obj) {
try {
OnTaskCompleteDelegate callback = new OnTaskCompleteDelegate(OnTaskComplete);
BoyceReporting.CallReport(boyce.BoyceThreadingEnvironment.OBRO, "THREADING");
HttpContext.Current = boyce.BoyceThreadingEnvironment.CONTEXT;
if (boyce.BoyceThreadingEnvironment.CTS.Token.IsCancellationRequested) {
boyce.BoyceThreadingEnvironment.SESSION.sScriptToExecute = "alert('Report Canceled By User');";
boyce.BoyceThreadingEnvironment.SESSION.bIsReportRunning = false;
callback("CANCELED");
} else {
boyce.BoyceThreadingEnvironment.SESSION.bIsReportRunning = false;
callback("FINISHED");
}
} catch {
throw;
}
}
Here is the web service method I created to monitor the process, with a built in safety net
--------------------------------------------------------------------------------------------
[WebMethod(EnableSession = true)]
public string WaitOnReport() {
try {
HttpContext.Current = boyce.BoyceThreadingEnvironment.CONTEXT;
SessionManager CurrentSession;
CurrentSession = (SessionManager)boyce.BoyceThreadingEnvironment.SESSION;
DateTime dtStartTime = DateTime.Now;
DateTime dtCurrentTime = DateTime.Now;
if (CurrentSession != null) {
do {
// Build a safety limit into this loop to avoid an infinate loope
// If this runs longer than 20 minutes, then force an error due to timeout
// This timeout should be lowered when they find out what the issue is with
// the "long running reports". For now, I set it to 20 minutes but shoud be MUCH lower.
dtCurrentTime = DateTime.Now;
TimeSpan span = dtCurrentTime-dtStartTime;
double totalMinutes = span.TotalMinutes;
if (totalMinutes>=20) {
return "alert('Error In Creating Report (Time-Out)');";
}
} while (CurrentSession.bIsReportRunning == true);
// If all goes well, return the script to either OPEN the report or display CANCEL message
return CurrentSession.sScriptToExecute;
} else {
return "alert('Error In Creating Report (Session)');";
}
} catch {
throw;
}
}
And here is the JavaScript code I used to initiate the Web Service Call and Also The Postback
--------------------------------------------------------------------------------------------
function jsWaitOnCallReport() {
try {
var oWebService = BoyceWebService.WaitOnReport(jsWaitOnCallReport_CallBack);
} catch (e) {
alert('Error In Calling Report Screen -- ' + e);
}
}
function jsWaitOnCallReport_CallBack(result) {
try {
eval(result);
var myExtender = $find('ModalPopupExtenderPROGRESS');
if (myExtender != null) {
try {
myExtender.hide();
} catch (e) {
// Ignore Any Error That May Be Thrown Here
}
}
$find('PROGRESS').hide();
} catch (e) {
alert('Error In Opening Report Screen -- ' + e);
}
}
Hope this helps someone else out.. Like I said, I am not sure this is the best solution, but it works.. I would be interested in other solutions for this issue to try... Thanks.