Solved

Weird issue with BackgroundWorker

Posted on 2011-09-22
22
326 Views
Last Modified: 2012-05-12
I am using a background worker in a winforms app which I have done several times.  However this time I am getting some weird results.  For one, when I run the function that uses the bgw, the UI for some reason goes unresponsive...something I have never seen in past usage.

Also, when I am trying to debug, I set a breakpoint on the DoWork event.  This gets hit normally, but my mouse cursor goes to a busy hourglass and just sits for about 4-5 seconds, then when I try to step to the next line, it is like I hit F5(run) and no more break points get hit...I also get no data returned and the app just acts like it is doing something, but it never returns.  The completed event never gets hit and the progress changed event doesn't get hit.

any thought...?  I have looked at old code where I have used this before and I am doing the exact same thing I always have...I have never seen this...
0
Comment
Question by:rgn2121
  • 13
  • 6
  • 3
22 Comments
 
LVL 17

Expert Comment

by:nepaluz
ID: 36581150
show us some code you are using.
0
 
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 36581151
Pretty impossible to say without seeing some code...especially the DoWork() handler.

Are you using any third-party components/libraries in the application?
0
 
LVL 12

Author Comment

by:rgn2121
ID: 36581190
I do use the MS Log Parser COM control....that is the only thing I use that is not standard within the IDE.


Private Sub mLogWorker_DoWork(ByVal sender As Object, _
                                  ByVal e As System.ComponentModel.DoWorkEventArgs) Handles mLogWorker.DoWork

        Dim query As String = TryCast(e.Argument, String)

        If Not String.IsNullOrEmpty(query) Then

            mEventLogInstance.direction = "BW"

            e.Result = CreateDataTableFromEventLogs(EventLogger.Execute(query, EventLogInstance))
        Else
            Throw New ArgumentNullException("e.Argument", "The query to process was missing.")
            e.Cancel = True
            Return
        End If

    End Sub ' mLogWorker_DoWork

Open in new window

0
 
LVL 12

Author Comment

by:rgn2121
ID: 36581302
Let me add a little background about what I am doing.  I have created a class to handle calls to server application logs.  The UI is used to allow the user to filter and sort and then I assemble the query and pass it in and run it.  If I just query the log, the codes runs and returns in about 1 sec.  If I do some filtering or sorting this might take a little longer, which is why I put the backgroundworker in.

This still works, but the UI freezes for some reason.  I set breakpoints on every line in the code above and once I hit the DOWork, it freezes for a few seconds and then I step in and nothing else gets hit and I get nothing returned...like the code goes someplace and is running but never comes back...
0
 
LVL 85

Assisted Solution

by:Mike Tomlinson
Mike Tomlinson earned 500 total points
ID: 36581317
Some ActiveX/COM controls silently marshal back to the main UI thread without you knowing.  Is line #10 hitting that Log Parser control?
0
 
LVL 12

Author Comment

by:rgn2121
ID: 36581353
yes, but when I debug and put breakpoints throughout that code, I never even get to line 4.  The code breaks on the DoWork and I get the hourglass.  I wait till it goes away and I try to step to line 4 and nothing else gets hit..it is just like what I would expect if I had no other break points set and I had hit F5...only I get no data.

It's like it works fine (other than the UI hanging) if I let it run....if I try to debug through no results.
0
 
LVL 12

Author Comment

by:rgn2121
ID: 36581367
And I don't see anything weird when the class itself gets created and those Log Parser objects get declared and instantiated.
0
 
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 36581372
Show us more code then...how are starting the BackgroundWorker()?
0
 
LVL 17

Expert Comment

by:nepaluz
ID: 36581381
is the e-argument actually a string? then try directcasting it
0
 
LVL 12

Author Comment

by:rgn2121
ID: 36581397
After I create the 'EventLogControl" object this is the routine that gets called and starts everything up...

Private mEventLogger As New LogQueryClass
    Private mEventLogInstance As New COMEventLogInputContextClass
    Private WithEvents mLogWorker As BackgroundWorker
    Private mDisposedValue As Boolean = False        ' To detect redundant calls
    Private Const EVENT_LOG_QUERY As String = "SELECT {0} TO_UPPERCASE( EXTRACT_TOKEN(EventTypeName, 0, ' ') ) " & _
                                                "as EventType, TimeGenerated as EventTS, " & _
                                                "SourceName as EventSource, " & _
                                                "EventID, " & _
                                                "Message as EventMessage " & _
                                            "FROM \\{1}\{2} "
    

Public Sub QueryEventLogAsync(ByVal logEntryCount As String, _
                                    ByVal whereClause As String, _
                                    ByVal orderClause As String, _
                                    ByVal serverName As String, _
                                    ByVal logType As EventLogType)

        Dim query As String = EVENT_LOG_QUERY

        'Get where clause
        If Not String.IsNullOrEmpty(whereClause) Then
            query += whereClause
        End If
        'Get order clause
        If Not String.IsNullOrEmpty(orderClause) Then
            query += orderClause
        End If

        Dim qryString As String = String.Format(query, _
                                                logEntryCount, _
                                                serverName, _
                                                logType.ToString)
        If mLogWorker Is Nothing Then
            mLogWorker = New BackgroundWorker
            mLogWorker.WorkerReportsProgress = True
            mLogWorker.WorkerSupportsCancellation = True
        ElseIf mLogWorker.IsBusy Then
            'wait
            MsgBox("A query is currently being processed, please wait.", _
                    MsgBoxStyle.Information, "Busy")
            Exit Sub
        End If

        mLogWorker.RunWorkerAsync(qryString)

    End Sub 'QueryEventLogAsync

Open in new window

0
 
LVL 12

Author Comment

by:rgn2121
ID: 36581425
is the e-argument actually a string? then try directcasting it
Yes it is, I did and I got the same result...
0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
LVL 17

Expert Comment

by:nepaluz
ID: 36581566
I'd declare Private WithEvents mLogWorker As BackgroundWorker as Public in the UI class /  form.
0
 
LVL 12

Author Comment

by:rgn2121
ID: 36581587
so you mean where I do...
Private WithEvents mTempLogParser As EventLogControl

in the UI/Form, you would make that public?  
0
 
LVL 12

Author Comment

by:rgn2121
ID: 36581611
I have never had to do that before, but I made the change and it didn't work.  One other thing to point out, I have another app that uses the backgroundworker in the same way and it works exactly as I expect...no issues.  Although, I coded that app against 2.0, this one with the issues is using 3.5.  Maybe I should try running this as a 2.0 app?
0
 
LVL 12

Author Comment

by:rgn2121
ID: 36581693
Well, I went ahead and changed to a 2.0 app and that didn't work either.
0
 
LVL 85

Assisted Solution

by:Mike Tomlinson
Mike Tomlinson earned 500 total points
ID: 36581915
I don't see any red flags in the code...leading me to believe it is just the COM component acting funny because it's being used from a secondary thread.

Try running it directly from the main UI thread to see if it at least completes (yes, it will still lock up).
0
 
LVL 12

Author Comment

by:rgn2121
ID: 36581982
Yes it completes fine from the main UI thread.  This is how I originally had it, but that was before I added in the ability to filter and order the result set.  I guess I will just have to deal with the UI locking up...?
0
 
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 36581993
"...but that was before I added in the ability to filter and order the result set."

Make sure that it also completes fine from the main UI with the filter and ordering code as well.

If that is the case, then I would say the COM control is incompatible with the BackgroundWorker control.
0
 
LVL 12

Author Comment

by:rgn2121
ID: 36582296
So far the one running on the UI thread with filtering isn't working...not sure why.  Giving an error about my query format, but I am running the exact same query...just different threads...

SELECT TOP 50 TO_UPPERCASE( EXTRACT_TOKEN(EventTypeName, 0, ' ') ) as EventType, TimeGenerated as EventTS, SourceName as EventSource, EventID, Message as EventMessage FROM \\Server\Application WHERE EXTRACT_TOKEN(EventTypeName, 0, ' ') <> 'Warning' Order By TimeGenerated

SELECT TOP 50 TO_UPPERCASE( EXTRACT_TOKEN(EventTypeName, 0, ' ') ) as EventType, TimeGenerated as EventTS, SourceName as EventSource, EventID, Message as EventMessage FROM \\Server\Application WHERE EXTRACT_TOKEN(EventTypeName, 0, ' ') <> 'Warning' Order By TimeGenerated

I pulled these out into UltraEdit and they are the same...unless I missed something.
0
 
LVL 12

Author Comment

by:rgn2121
ID: 36582325
Scratch that last comment...I had passed the wrong variable when I was cutting out the BGW.  Everything runs fine and returns as it should.  The query takes about 14 seconds in both systems and both lock the UI...but the one with out the BGW can be debugged as expected.  

Maybe I should try running it using system.threading.thread?  Or is that a waste of my time?
0
 
LVL 85

Accepted Solution

by:
Mike Tomlinson earned 500 total points
ID: 36582707
Hmmm...I think the BackgroundWorker utilizes the Thread Pool, which is MTA.

With a manual thread, we can set it explicitly to STA:

    Dim T As New Thread(AddressOf Foo)
    T.ApartmentState = ApartmentState.STA
    T.Start()

That might make the COM control happier.

Of course, now you have to do the marshalling manually with delegates and BeginInvoke() to update any controls back on the main UI thread.
0
 
LVL 12

Author Comment

by:rgn2121
ID: 36598445
For the project I am doing it isn't all that important to worry with having it on another thread.  I was more curious about the weird behavior.  If I do decide to come back to this just to test it out, I will comment on what I find...Thanks!
0

Featured Post

Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

Join & Write a Comment

This article is meant to give a basic understanding of how to use R Sweave as a way to merge LaTeX and R code seamlessly into one presentable document.
Although it can be difficult to imagine, someday your child will have a career of his or her own. He or she will likely start a family, buy a home and start having their own children. So, while being a kid is still extremely important, it’s also …
In this fourth video of the Xpdf series, we discuss and demonstrate the PDFinfo utility, which retrieves the contents of a PDF's Info Dictionary, as well as some other information, including the page count. We show how to isolate the page count in a…
In this fifth video of the Xpdf series, we discuss and demonstrate the PDFdetach utility, which is able to list and, more importantly, extract attachments that are embedded in PDF files. It does this via a command line interface, making it suitable …

758 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

23 Experts available now in Live!

Get 1:1 Help Now