Link to home
Start Free TrialLog in
Avatar of pclarke7
pclarke7

asked on

C# StartBackgroundProcess not runing Async

I have a C# WCF Service hosted in IIS 8.5 which has a simple Client webform consisting of a ComboBox for data entry. The ComboBox can be populated manually or via barcode scanner on the users mobile device. Every time the user uses scanned input the scanned value is written to a database table with UserId, dateTime & value. I have an API which will return the last scanned input for a user based on dateTime scanned.

So I now have a webform which can take its input either manually or via scanned input. If there is no selected value in the comboBox then I want to run a background job to call the API and return any scanned input value to the ComboBox.  

CheckForScannedTransactions below is part of the Client WebForm1 and it calls the background job StartBackgroundProcess passing parameters MyBGJobParms. I expected control to return to UI but when there is no scanned input to return control never returns to the UI despite RunWorkerAsync. Why is this ?

In this scenario every logged on user will call CheckForScannedTransactions() to check for their own scanned input. Is there a better way of doing this ? Could I for instance have just 1 background job running continuously and updating scanned input to each users webform page. Is that possible if so How so?



//CheckforSacnnedTransactions will run in background and populate any scanned value to ComboBox if ComboBox is empty 
if (ComboBox1.SelectedIndex == -1 )
{
    CheckForScannedTransactions ();
}

Open in new window


public void  CheckForScannedTransactions()
        {
            BGJobParms MyBGJobParms= new BGJobParms();
            MyBGJobParms.BGJobName = "BGJOB01";
            MyBGJobParms.BGJobDescription = "Check for Barcode Scanned Transactions";
            MyBGJobParms.BGJobThreadName = "TiosClientBackgroundWorkerThread";
            MyBGJobParms.BGJobMaxRunSeconds = 0;
            MyBGJobParms.BGJobParm1 = MyRtnFromServiceParms.passedEnterpriseId;
            MyBGJobParms.BGJobParm2 = MyRtnFromServiceParms.passedUserId;
            MyBGJobParms.BGJobTransName = MyRtnFromServiceParms.passedCurrentTransId;
            MyBGJobParms.BGJobTransSeq = MyRtnFromServiceParms.passedCurSeq;
            BGWorker MyBGWorker = new BGWorker();

            // Pass BGWorker & BGWorker Parameters to Background job 
            MyBGWorker.ReceiveMyBGWorker(MyBGWorker);
            MyBGWorker.ReceiveMyBGJobParms(MyBGJobParms);

            // Pass MyWebForm1 to Background job to enable call back with results 
            WebForm1 MyWebForm1 = HttpContext.Current.Handler as WebForm1;
            MyBGWorker.ReceiveMyWebForm1(MyWebForm1);

            // Call Background Job
            MyBGWorker.StartBackgroundProcess(MyBGJobParms);
        }

Open in new window


        public void StartBackgroundProcess(BGJobParms MyBGJobParms)
        {
            try
            {
                if (MyGlobals.logger2 == null)
                {
                    MyGlobals.logger2 = new LoggerConfiguration()
                   .ReadFrom.AppSettings()
                   .CreateLogger();
                    Log.Logger = MyGlobals.logger2;
                }
                MyGlobals.logger2.Information("START BGJ:   Enterprise: {Enterprise} User: {UserName} Trans: {Trans}  Seq: {Seq} Action: {action} MaxTime {Max} ",  MyBGJobParms.BGJobParm1, MyBGJobParms.BGJobParm2, MyBGJobParms.BGJobTransName, MyBGJobParms.BGJobTransSeq, MyBGJobParms.BGJobAction, MyBGJobParms.BGJobMaxRunSeconds);

            }

            catch (Exception ex)
            {

                MyGlobals.logger2.Error("START BGJ2: { BackgroundCancelError}  Enterprise: {Enterprise} User: {UserName} Trans: {Trans}  Seq: {Seq} Action: {action} MaxTime {Max} ", ex.Message.ToString(),MyBGJobParms.BGJobParm1, MyBGJobParms.BGJobParm2, MyBGJobParms.BGJobTransName, MyBGJobParms.BGJobTransSeq, MyBGJobParms.BGJobAction, MyBGJobParms.BGJobMaxRunSeconds);

            }

            // Create a background worker thread that ReportsProgress &
            // SupportsCancellation
            // Hook up the appropriate events.

            bg_Worker = new BackgroundWorker();
            bg_Worker.DoWork += new DoWorkEventHandler(bg_Worker_DoWork);
            bg_Worker.ProgressChanged += new ProgressChangedEventHandler
                    (bg_Worker_ProgressChanged);
            bg_Worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bg_Worker_RunWorkerCompleted);
            bg_Worker.WorkerReportsProgress = true;
            bg_Worker.WorkerSupportsCancellation = true;

            //
            // Start Background job
            //
            bg_Worker.RunWorkerAsync(MyBGJobParms);  // Call backgroundWorker with list of jobs to run MyBGJobParms parameter is accepted as e.Arguement
        }

Open in new window

Avatar of ste5an
ste5an
Flag of Germany image

Well, I don't understand why you need this thread at all? What is its purpose? Sounds like it is just querying the database...

As long as you don't allow multiple logins per user at the same time, there is imho no use-case for doing this as thread and permanently. But in this case I think you should take a look at React. Cause when there is something found,  a push makes more sense.
Avatar of pclarke7
pclarke7

ASKER

Hi Ste5an,
the reason why I need a background thread is as follows:

If user runs a transaction , for example, to receive a purchase order. They are prompted to enter the purchase order number which they can do manually of via scanner on  mobile phone app. If they use the mobile phone app to scan the PO number then the scanned value is written to a database table on server with their userId , scanned value and date/time of scan. The background job is constantly looking for any scan from this user with a date/Time > date/Time that PO input was prompted.   If they were using a wedge scanner connect by USB then I would agree that there would be no reason for a background job.

I'm relatively new to C# and ASP.NET and not familiar with SignalR  or React/Cause. Would you be able to point me towards any examples  ?
ASKER CERTIFIED SOLUTION
Avatar of ste5an
ste5an
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Apologies for delay in getting back.
First of all for anyone in the future reading this with a similar issue. The reason why UI was frozen when I was calling the background job was because I was calling the background job before Page_load was completed. This had the effect of freezing UI until the background job was finished.

I decided to take Ste5an's advice and look at an alternative way of pushing the data when it arrives rather than continuously polling. This has taken me to signalR which looks like it is perfect for this type of process. I am still trying to get a simple connection up and running. I have one issue. My WCF service is hosted in IIS and therefore I am not sure where to wire up the call to  app.MapSignalR();  This would normally be called in a startup program but when the WCF service is hosted in IIS I'm not sure where this should be placed ?  Any suggestions would be great before I close this ticket.

regards
Pat