Solved

asp.net BackGroundWorker RunWorkerCompleted

Posted on 2013-12-02
11
804 Views
Last Modified: 2014-02-19
I have an async process called from javascript using a PageMethod that executes a potentially long running process and updates a progress bar.  I'm trying to capture any errors/messages from the async process and report it to the user on a page control.  Tried sending a message from RunWorkerCompleted to the async success callback, but with no luck.

any help would be greatly appreciated.

Including relevant code.

thanks

// ** aspx code behind

Imports System.ComponentModel
Imports System.Threading
Imports System.Web.Services


    Protected Shared Sub ExportTaxesServices(ByVal sender As Object, ByVal e As DoWorkEventArgs)
        Dim dt As New DataTable

        ' Do the long running process
        Try
            args = CType(e.Argument, List(Of String))

            ' run the method to get rows for the datatable.   excluded for clarity
            For Each row As DataRow In dt.Rows

                    ' Calculate the percentage complete for this routine
                    percentComplete = Convert.ToInt32(i * 100 / rowCount)

                    ' Send the percentage complete to the async process that updates the rogress bar
                    bgWorker.ReportProgress(percentComplete)
                    i += 1
            Next
        Catch ex As Exception
            Throw ex
        End Try

    End Sub


    ' Return the percentage completed  
    <WebMethod()> _
    Public Shared Function Progress() As Integer
        Return percentage

    End Function

    ' Cancel the async call
    <WebMethod()> _
    Public Shared Sub CancelAsync()
        bgWorker.CancelAsync()

    End Sub

    ' Main routine that initiates the async call
    <WebMethod()> _
    Public Shared Sub RunAsync(ByVal taxType As String, ByVal invoiceDate As String, ByVal startDate As String, ByVal endDate As String, _
                               ByVal cycleID As String, ByVal userID As String)

        ' Add the list of parameters received from the javascript async call to a List
        Dim args As New List(Of String)
        args.Add(invoiceDate)
        args.Add(startDate)
        args.Add(endDate)
        args.Add(cycleID)
        args.Add(userID)

        percentage = 0

        ' Create the backgroundworker to execute the async calls on a separate thread
        bgWorker = New BackgroundWorker()
        bgWorker.WorkerReportsProgress = True
        bgWorker.WorkerSupportsCancellation = True

        Select Case taxType
            ' Set which routine will be run asynchronously
            Case "Services"
                AddHandler bgWorker.DoWork, AddressOf ExportTaxesServices

            Case "Usage"
                AddHandler bgWorker.DoWork, AddressOf ExportTaxesUsage

        End Select

        ' Set the routine that will be called when the progess of the async call changes
        AddHandler bgWorker.ProgressChanged, AddressOf bgWorker_ProgressChanged
        AddHandler bgWorker.RunWorkerCompleted, AddressOf bgWorker_Completed

        ' Start the async process, passing in the parameters
        Try
            bgWorker.RunWorkerAsync(args)
        Catch ex As Exception
            Throw ex
        End Try

    End Sub

    ' Gets the percentage completed of the async call
    Private Shared Sub bgWorker_ProgressChanged(ByVal sender As Object, ByVal e As ProgressChangedEventArgs)
        percentage = e.ProgressPercentage

    End Sub
    Private Shared Function bgWorker_Completed(ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs) As String
        Return "ok"

    End Function

// ** aspx javascript code

    <script type="text/javascript" language="javascript">

        var stopped = false;
        // Starts the async process with parameters if page passes validation
        if (Page_ClientValidate()) {
            function beginRequestHandler(sender, args) {
                stopped = false;
                var invoiceDate = new Date($get('<%= txtInvoiceDate.ClientID %>').value);
                invoiceDate = invoiceDate.getFullYear() + "-" + (invoiceDate.getMonth() + 1) + "-" + invoiceDate.getDate();

                var startDate = new Date($get('<%= txtStartDate.ClientID %>').value);
                startDate = startDate.getFullYear() + "-" + (startDate.getMonth() + 1) + "-" + startDate.getDate();

                var endDate = new Date($get('<%= txtEndDate.ClientID %>').value);
                endDate = endDate.getFullYear() + "-" + (endDate.getMonth() + 1) + "-" + endDate.getDate();

                var ddlCycleID = $get('<%= ddlBillingCycle.ClientID %>');
                var cycleID = ddlCycleID.options[ddlCycleID.selectedIndex].value;

                var ddlType = $get('<%= ddlType.ClientID %>');
                var taxType = ddlType.options[ddlType.selectedIndex].value;

                var userID = '<%= Session("UserID") %>';

                $get('<%= btnConfirm.ClientID %>').disabled = 'disabled';
                $get('<%= btnCancel.ClientID %>').disabled = 'disabled';
                $get('<%= progressPercent.ClientID %>').innerHTML = '0%';
                $get("<%= panelMessages.ClientID %>" + "_MessagePanel").style.display = 'none';
                $get('progressBar').style.width = '0%';
                PageMethods.RunAsync(taxType, invoiceDate, startDate, endDate, cycleID, userID, runAsyncSuccess, runAsyncFailure);
                setTimeout("progressChanged()", 10);
            }
        }

        // Closes the progress bar window and calls the function to refresh grid with results after the async call completes successfully.
        function runAsyncSuccess(result) {
            if (!stopped) {
                $find('modalProgressBehaviorID').hide();
                $get('<%= btnConfirm.ClientID %>').disabled = '';
                $get('<%= btnCancel.ClientID %>').disabled = '';
                $get('<%= btnCalculate.ClientID %>').disabled = 'disabled';
                refreshGrid('<%=hfRefereshGrid.ClientID %>');
                alert(result.get_message());
            }
            stopped = false;
        }

        function runAsyncFailure(result) {
            alert(result.get_message());
        }

        // Calls the Progress method to get the percent complete of the async process
        function progressChanged() {
            PageMethods.Progress(progressSuccess);
        }

        // Updates the progress bar with the percent complete of the async process
        function progressSuccess(response) {
            $get('<%= progressPercent.ClientID %>').innerHTML = response + '%';
            $get('progressBar').style.width = response + '%';
            setTimeout("progressChanged()", 10);
        }

        // Cancels the async process
        function cancelAsync() {
            stopped = true;
            PageMethods.CancelAsync();
        }

        // Refreshes the the grid with the results using an async postback
        function refreshGrid(hiddenFieldID) {
            var hiddenField = $get(hiddenFieldID);
            if (hiddenField) {
                hiddenField.value = (new Date()).getTime();
                __doPostBack(hiddenFieldID, '');
            }
        }
       
   </script>
0
Comment
Question by:dthansen
  • 5
  • 4
11 Comments
 
LVL 15

Expert Comment

by:VincentPuglia
ID: 39691513
Hi,
my familiarity with ASP is limited to the zoo; however, is this:

$get("<%= panelMessages.ClientID %>" + "_MessagePanel").style.display = 'none';

where you expect to see the messages?  If so, where are you resetting 'display' to 'visible' or 'block'?
0
 
LVL 15

Expert Comment

by:VincentPuglia
ID: 39691515
and where is result's method defined?
 
 alert(result.get_message());
0
 

Author Comment

by:dthansen
ID: 39692902
$get("<%= panelMessages.ClientID %>" + "_MessagePanel").style.display = 'none';

isn't where I'm expecting to see the results,  that line is just hiding that control


where I am expecting to see messages is in this function where I pass in the result after the async call finishes

        function runAsyncSuccess(result) {
            if (!stopped) {
                $find('modalProgressBehaviorID').hide();
                $get('<%= btnConfirm.ClientID %>').disabled = '';
                $get('<%= btnCancel.ClientID %>').disabled = '';
                $get('<%= btnCalculate.ClientID %>').disabled = 'disabled';
                refreshGrid('<%=hfRefereshGrid.ClientID %>');
                alert(result.get_message());
            }
            stopped = false;
        }
 
I was thinking that this would pass the result back to runAsyncSuccess function

    Private Shared Function bgWorker_Completed(ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs) As String
        Return "ok"

    End Function

maybe that is incorrect

thanks
0
 
LVL 15

Expert Comment

by:VincentPuglia
ID: 39693175
Ok, but unless I'm reading it all wrong....
1) you are getting values, but where are you putting them?
as in:  var confirmBut = $get('<%= btnConfirm.ClientID %>').disabled = '';

2) you're presuming the alert has all of the information, where is result's get_message() method defined?    result.get_message());
0
What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

 

Author Comment

by:dthansen
ID: 39693475
Hi Vincent

$get('<%= btnConfirm.ClientID %>').disabled = '';  
just disables the btnConfirm control on the aspx page.   $get is asp.net's shorthand for the javascript document.getElementById function.  no need to put that value anywhere

as far as I understand .get_message() is a built in javascript function that is supposed to extract any messages that are in the result object which is returned from the async call.

thanks
0
 
LVL 15

Expert Comment

by:VincentPuglia
ID: 39693533
sorry, but there is no obj.get_message() within 'vanilla' javascript.   I did see one mentioned for json
 msdn library
0
 

Author Comment

by:dthansen
ID: 39693628
ok, thanks Vincent.  I'll look into that
0
 
LVL 15

Expert Comment

by:VincentPuglia
ID: 39693649
In the meanwhile, you could try something like this:

get the values you need to look at, store them into a protected string (array, etc) and then send that string to javascript

var myValues = "<%= myProtectedString %>";

you can then alert(myValues)
0
 

Accepted Solution

by:
dthansen earned 0 total points
ID: 39731923
This has been resolved.

Here is what I needed to do:

changed the the RunWorkerCompleted Sub to

    ' Gets the result of the async call when completed and reports any errors that may have occurred
    Private Shared Sub bgWorker_Completed(ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs)
        If e.Error IsNot Nothing Then
            asyncErrMessages = e.Error.Message
            Throw New Exception(asyncErrMessages)
        End If
    End Sub


In my aysnc routine if any errors occur I throw it from a try...catch.  the RunWorkerCompleted sub will catch the error

added this function that will return the error to the browser;
    <WebMethod()> _
    Public Shared Function AsyncErrors() As String
        Return asyncErrMessages
    End Function


added the following javascript to the page to display the error to the user:

        function runAsyncFailure() {
            PageMethods.AsyncErrors(asyncErrors)
        }

        function asyncErrors(result) {
            $get('btnCancelAsync').click();
            var msgPanel = $get("<%= panelMessages.ClientID %>" + "_MessagePanel");
            msgPanel.style.display = 'block';
            msgPanel.className = 'error';
            msgPanel.innerHTML = result;
        }
0

Featured Post

Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

Join & Write a Comment

Just a quick little trick I learned recently.  Now that I'm using jQuery with abandon in my asp.net applications, I have grown tired of the following syntax:      (CODE) I suppose it just offends my sense of decency to put inline VBScript on a…
It was really hard time for me to get the understanding of Delegates in C#. I went through many websites and articles but I found them very clumsy. After going through those sites, I noted down the points in a easy way so here I am sharing that unde…
The viewer will learn the basics of jQuery, including how to invoke it on a web page. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery.: (CODE)
The viewer will learn the basics of jQuery including how to code hide show and toggles. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery…

759 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

17 Experts available now in Live!

Get 1:1 Help Now