[Webinar] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1220
  • Last Modified:

using a thread to call my function

Hi,

I havent really used threads before so need a bit of help.

I have a button that when click will basically call a stored procedure that will take a long time to run around 30 mins due to the processing it will do.

I have a user interface to do this.

On the button click I have the function below.

What I am basically trying to do is display the page to show the process is running and then start the thread calling my function that exectues the upload.

The function is as follows:

Private Sub ExecuteUpload()
        Try
            'CLDataAccess.ExecuteNonQuery(_strUploadStoredProcedureName)

            'Once the thread has finished we need to display this to the user and amend the user interface accordingly.
            DisplayPageInUploadedStatus()
        Catch ex As Exception
            Throw
        End Try

I have commented the call to the stored proc out at the moment.

But once the stored proc has finished I want the page to then be updated with details stating it has finished etc.

The ExecuteUpload is being hit but it doesnt seem to be stepping into the try block to hit the function DisplayPageInUploadedStatus.

Can anyone see why?

Is my logic ok in that once the stored proc has finished running the thread will call my function to update the page to say it has finished?

Thanks in advance.


Protected Sub btnStartUpload_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnStartUpload.Click
        Dim uploadThread As Thread
 
        Try
            SetRequiredUpload()
 
            DisplayPageInUploadingStatus()
 
            'set execution running in its own thread
            uploadThread = New Thread(AddressOf ExecuteUpload)
            uploadThread.Start()
 
        Catch ex As Exception
            Throw
        End Try

Open in new window

0
scm0sml
Asked:
scm0sml
  • 7
  • 4
1 Solution
 
carlnorrbomCommented:
Hi,

For reference on how to adress background worker threads and updating the webform UI, please refer to the attached code as an example.

/Carl.
WorkerThreadPage.aspx:
 
<%@ Page Language="VB" AutoEventWireup="false" CodeFile="WorkerThreadPage.aspx.vb" Inherits="WorkerThreadPage" %>
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Background Worker Thread Test</title>
</head>
<body>
    <form id="form1" runat="server">
    <asp:ScriptManager ID="ScriptManager1" runat="server">
    </asp:ScriptManager>
    <div style="border: Solid 1px Gray;padding: 5px 5px 5px 5px;margin-top: 50px;">
        <asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional" ChildrenAsTriggers="False">
            <ContentTemplate>
                <div id="processDiv" runat="server">
                </div>           
            </ContentTemplate>
            <Triggers>
                <asp:AsyncPostBackTrigger ControlID="Timer1" EventName="Tick" />
            </Triggers>
        </asp:UpdatePanel>
        <asp:Button ID="btnStartProcess" Text="Start Background Process" runat="server" />
        <asp:Timer ID="Timer1" runat="server" Interval="1000">
        </asp:Timer>
    </div>
    </form>
</body>
</html>
 
WorkerThreadPage.aspx.vb:
 
Imports System.Threading
 
Partial Class WorkerThreadPage
    Inherits System.Web.UI.Page
 
    Private Event ThreadCompleted()
    Private Event ThreadProgress(ByVal threadProgress As Double)
 
    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        If Not Page.IsPostBack Then
            Dim wThread As Thread = New Thread(AddressOf DoBackgroundWork)
            wThread.IsBackground = True
            Session("WorkerThread") = wThread
            AddHandler ThreadCompleted, AddressOf WorkerThreadCompleted
            AddHandler ThreadProgress, AddressOf WorkerThreadProgress
            Timer1.Enabled = False
            Session("IsComplete") = False
            Session("MaxRunningTime") = 100
            Session("ThreadProgress") = 0
        End If
        If Page.IsPostBack Then
            If (CType(Session("WorkerThread"), Thread).IsAlive = True) And (CType(Session("IsCompleted"), Boolean) = True) Then
                CType(Session("WorkerThread"), Thread).Abort()
            End If
        End If
    End Sub
 
    Protected Sub btnStartProcess_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnStartProcess.Click
        CType(Session("WorkerThread"), Thread).Start()
        processDiv.InnerText = "Processing Background Worker Thread, Status: 0%"
        Timer1.Enabled = True
    End Sub
 
    Private Sub DoBackgroundWork()
        Dim i As Integer = 0
        Do While i < CInt(Session("MaxRunningTime")) + 1
            If (i = CInt(Session("MaxRunningTime"))) Then
                RaiseEvent ThreadCompleted()
            End If
            RaiseEvent ThreadProgress(CDbl(100 * (i / CInt(Session("MaxRunningTime")))))
            Thread.Sleep(1000)
            i += 1
        Loop
        i = 0
    End Sub
 
    Private Sub WorkerThreadCompleted()
        Session("IsCompleted") = True
    End Sub
 
    Private Sub WorkerThreadProgress(ByVal threadProgress As Double)
        If threadProgress.ToString.Length > 5 Then
            Session("ThreadProgress") = threadProgress.ToString.Substring(0, 5)
        Else
            Session("ThreadProgress") = threadProgress.ToString
        End If
    End Sub
 
    Protected Sub Timer1_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        processDiv.InnerText = "Processing Background Worker Thread, Status:" & Session("ThreadProgress").ToString & "%"
        If Session("IsCompleted") Then
            processDiv.InnerText = "Processing Background Worker Thread, Status: Finished!"
            Timer1.Enabled = False
        End If
    End Sub
 
End Class

Open in new window

0
 
scm0smlAuthor Commented:
is there not another way other than ajax?
0
 
carlnorrbomCommented:
Hi,

Well, You could have asked that in your other question. There might be, however as far as I know the http.response object is not allowed in the background context where the worker thread is running, making it hard to update the ui. I figure ajax / client side checking is most efficient, otherwise setting up a service call (which would still need client side checking).

/Carl.
0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
scm0smlAuthor Commented:
ok i have installed AJAXExtensionsToolbox.

Is that what is required for your work?

I have added a reference to it in the site but it doesnt like all your ajax components so i assume i have done something wr0ong or this isnt the correct thing to install?
0
 
carlnorrbomCommented:
Hi,

It should only require Ajax extensions. If You drag an Ajax component from the toolbox onto the page it should register the ajax assembly with a certain prefix, i.e:

<%@ Register Assembly="AjaxExtensions" Namespace="AjaxExtensions" TagPrefix="Ajax" %>

You then need to make sure that the ajax components in the code are using that specific tag prefix. You should change:

<asp:ScriptManager... to <YourPrefix:ScriptManager...

<asp:UpdatePanel... to <YourPrefix:UpdatePanel...

<asp:AsyncPostBackTrigger... to <YourPrefix:AsyncPostBackTrigger...

<asp:Timer... to <YourPrefix:Timer...

Those are the only Ajax elements in the code.

/Carl.
0
 
scm0smlAuthor Commented:
scrap that i hadnt made an changes to my webconfig file.

ok i am going to try again with your suggestion and see how i get on.
0
 
scm0smlAuthor Commented:
yeah ok i have got that working fine now.

so in the DoBackgroundWork() i call my sp correct?

and then in WorkerThreadCompleted() i would update labels etc

im not interested in the timer etc for my work correct?

and the labels to be changed will need to be inside my update panel?
0
 
scm0smlAuthor Commented:
also can i ask why u have put the workerthread in a session?
0
 
scm0smlAuthor Commented:
right ive got everything working nicely now using your example as a base so thanks for that.

my only concern is the use of the session.

like i say my stored proc is going to take some time to run and im worried about sessions timing out etc.

i could have a duration label on the page to help keep accessing certain sessions if that would help.

is it necassary though?

once i have this answer i think im just about there :)
0
 
carlnorrbomCommented:
Hi again,

Well, the use of the Session variable is only because it's convinient. The nature of a webform and the continuos posting back to the server makes it a suitable solution. I guess you might be able to declare private variables on a class level but not sure whether they will be maintained cross postbacks or not.

If you keep the timer it will keep polling the server and maintain your session. If you don't want it to be that fluent you might might just change the interval to let's say 60000, then it will check and update your ui once a minute.

/Carl.
0
 
scm0smlAuthor Commented:
got there in the end :)
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 7
  • 4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now