Pergunta

I have searched for several days now, and have tried about every solution that I could find. I know this is something I am not doing correctly, however, I am not sure what the correct way is.

I have an ASP.Net C# web site, running on .Net Framework 4.5. I have a link button on a form, that when clicked fires off a long running process using the ThreadPool. I have a delegate callback setup, and the code does fire when the process is canceled or when it finishes. (I am using the Cancelation Token for canceling the process and the process is Active Reports in case that matters.)

Like I said, everything works great, except for when the callback code fires it does not execute the javascript. (FYI -- this is NOT a javascript callback, just trying to fire off some javascript code when the process finishes.)

Here is the code that i start the report...

string sThreadID = Thread.CurrentThread.ManagedThreadId.ToString(); ThreadPool.QueueUserWorkItem(new WaitCallback(StartReport), cts.Token);

Here is the code for the StartReport....

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;
    }
}

Here is the code for the CallBack code.....

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;
    }
}

Here is the issue that I am having.....

Everything works fine except i can not get the last line of code to fire the script. ScriptManager.RegisterStartupScript

Here is what I think is happening.....

From looking at the thread ID, I am sure the reason that the code is not firing is because the ScriptManager code that I am trying to fire in the Call Back event is on a different thread, other than the main thread.

Here is my question(s).....

(1) Am I correct in why this is not firing the JavaScript (2) How can I (from inside of the CallBack) get this JavaScript to fire? Is there a way to force this to execute on the main Thread?

Foi útil?

Solução 2

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.

Outras dicas

It's not firing in JS because you're spinning off a new thread. In the meantime, the request has long since returned to the client and closed the connection. By the time the thread tries to write something out to the Response, it's already finished.

Instead of doing it this way, just have your button click (or whatever it is that kicks off the report), inside of an UpdatePanel. Then, you don't need to fire off a new thread.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top