-
Oct 24th, 2013, 05:11 PM
#1
Thread Starter
Member
BackroundWorker Problem that I can't figure out
Hello all, I have been having some trouble ever since I implemented this background worker code.
My program simply loads a script (simply a file with one line containing a REGEX, although the script can contain more then one line of REGEX) and runs the check against everyline of every log file. When I run the script (by clicking Run) it seems to work perfectly, but if I either Press Stop, OR, wait for it to finish, the whole program freezes up for about 5 seconds, and then what I see in the first screenshot, turns into the second screenshot... Any help?
This is just a snippet of the code, but I can post the whole lot upon request. Thanks
Code:
Imports System
Imports System.IO
Imports System.Text
Imports System.Text.RegularExpressions
Imports System.ComponentModel
Public Class MainWindow
Public num_logs As Integer
Public num_scripts As Integer
Public script_error As Integer
Public script_edisc As String
Public script_file As String
Public script_letter As String
Public script_loop As Decimal
Public log_file As String
Public log_letter As String
Public log_loop As Decimal
Public sr As StreamReader
Public lr As StreamReader
Public read_file_line As String
Public current_script As String
Public running_script As String
Public script_line As String
Public log_line As String
Public script_param As Array
Public script_text As String
Public script_docu As String
Public response As Boolean
Public editmode As Integer
Public script_regex As Regex
Public script_m As Match
Public running_bg As Integer
Private Sub ToolStripButton5_Click(sender As System.Object, e As System.EventArgs) Handles ToolStripButton5.Click
If (ListBox2.Items.Count < 1) Then
MsgBox("There are no items in the script list. There needs to be at least one script selected before you can run it.", MsgBoxStyle.OkOnly, "Run Script")
Else
If (CheckedListBox1.Items.Count < 1) Then
MsgBox("The logs list is empty. There are no logs to run this script against.", MsgBoxStyle.OkOnly, "Run Script")
Else
If Not BackgroundWorker1.IsBusy = True Then
BackgroundWorker1.RunWorkerAsync()
running_bg = 1
End If
End If
End If
End Sub
Private Sub MainWindow_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = False
~ More Code ~
End Sub
Private Sub BackgroundWorker1_DoWork(sender As System.Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
Dim worker As System.ComponentModel.BackgroundWorker
worker = CType(sender, System.ComponentModel.BackgroundWorker)
current_script = ListBox2.GetItemText(ListBox2.SelectedItem)
TabControl1.SelectTab(1)
If current_script <> "" Then
running_script = "Running '" + current_script + "' script on selected log files..."
al(running_script)
script_error = 0
script_edisc = ""
For Each logfile In CheckedListBox1.CheckedItems()
log_file = ToolStripTextBox2.Text + "\" + logfile.ToString + ".log"
ListBox3.Items.Add("Running script on " + log_file + "...")
Me.Refresh()
lr = New StreamReader(log_file)
Do
log_line = lr.ReadLine()
If log_line <> "" Then
sr = New StreamReader("scripts/" + current_script + ".lcs")
Do
script_line = sr.ReadLine()
If (script_line <> "") Then
If running_bg = 0 Then
Exit Do
End If
If script_line.Length > 6 Then
If (script_line.Substring(0, 6) = "MATCH ") Then
Dim script_regex As New Regex(script_line.Substring(6))
Dim script_m As Match = script_regex.Match(log_line)
If script_m.Success Then
ListBox3.Items.Add(log_line)
Me.Refresh()
End If
End If
End If
End If
Loop Until script_line Is Nothing
End If
If running_bg = 0 Then
Exit Do
End If
Loop Until log_line Is Nothing
ListBox3.Items.Add("Finished running script on " + log_file + "...")
Me.Refresh()
If running_bg = 0 Then
Exit For
End If
Next
al("Script has finished running.")
Me.Refresh()
End If
End Sub
Private Sub ToolStripButton11_Click(sender As System.Object, e As System.EventArgs) Handles ToolStripButton11.Click
If BackgroundWorker1.WorkerSupportsCancellation = True Then
BackgroundWorker1.CancelAsync()
running_bg = 0
End If
End Sub
Private Sub BackgroundWorker1_RunWorkerCompleted(ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
If e.Error IsNot Nothing Then
al("Error: " & e.Error.Message)
ElseIf e.Cancelled Then
al("Script did not finish as it was stopped.")
Else
al("Done!")
End If
End Sub
End Class
-
Oct 24th, 2013, 05:40 PM
#2
Re: BackroundWorker Problem that I can't figure out
all of those controls you're accessing in your background thread need to be invoked on that thread
- Coding Examples:
- Features:
- Online Games:
- Compiled Games:
-
Oct 24th, 2013, 05:42 PM
#3
Thread Starter
Member
Re: BackroundWorker Problem that I can't figure out
I'm sorry, this is my first time using BackgroundWorkers, how does one invoke?
-
Oct 24th, 2013, 05:50 PM
#4
Re: BackroundWorker Problem that I can't figure out
here's an example:
Code:
Public Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
BackgroundWorker1.RunWorkerAsync()
End Sub
Private Sub BackgroundWorker1_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
For x As Integer = 1 To 10
setText(x.ToString)
MsgBox(getText)
Next
End Sub
Private Delegate Sub setTextCallBack(ByVal newValue As String)
Private Sub setText(ByVal newValue As String)
If TextBox1.InvokeRequired Then
TextBox1.Invoke(New setTextCallBack(AddressOf setText), newValue)
Else
TextBox1.Text = newValue
End If
End Sub
Private Delegate Function getTextCallBack() As String
Private Function getText() As String
If TextBox1.InvokeRequired Then
Return DirectCast(TextBox1.Invoke(New getTextCallBack(AddressOf getText)), String)
Else
Return TextBox1.Text
End If
End Function
End Class
- Coding Examples:
- Features:
- Online Games:
- Compiled Games:
-
Oct 25th, 2013, 05:41 AM
#5
Re: BackroundWorker Problem that I can't figure out
Originally Posted by .paul.
here's an example:
Code:
Public Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
BackgroundWorker1.RunWorkerAsync()
End Sub
Private Sub BackgroundWorker1_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
For x As Integer = 1 To 10
setText(x.ToString)
MsgBox(getText)
Next
End Sub
Private Delegate Sub setTextCallBack(ByVal newValue As String)
Private Sub setText(ByVal newValue As String)
If TextBox1.InvokeRequired Then
TextBox1.Invoke(New setTextCallBack(AddressOf setText), newValue)
Else
TextBox1.Text = newValue
End If
End Sub
Private Delegate Function getTextCallBack() As String
Private Function getText() As String
If TextBox1.InvokeRequired Then
Return DirectCast(TextBox1.Invoke(New getTextCallBack(AddressOf getText)), String)
Else
Return TextBox1.Text
End If
End Function
End Class
While this would work, this seems to defeat the whole purpose of the BackgroundWorker class. The background worker class was really meant to avoid this type of code. It has all the logic already built into it.
Whenever you want to access any UI element, do that via the ReportProgress method and ProgressChanged event. You can pass the ProgressPercentage to the ProgressReport method, telling it how much of your work is complete. Additionally you can pass it the UserState parameter with whatever value you want and do UI related things with that, if required. These two things are available for use in the ProgressChanged event handler.
Here is an example of how to do it the proper way, avoiding delegates:
Put a TextBox, a ProgressBar, and two Buttons on a form and the following code.
vb.net Code:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click ProgressBar1.Maximum = 100 ProgressBar1.Value = 0 BackgroundWorker1.WorkerReportsProgress = True BackgroundWorker1.WorkerSupportsCancellation = True BackgroundWorker1.RunWorkerAsync() End Sub Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click ' Cancel button BackgroundWorker1.CancelAsync() End Sub Private Sub BackgroundWorker1_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork Const MAX As Integer = 1000 For i As Integer = 1 To MAX ' some delay to simulate work in progress Threading.Thread.Sleep(100) ' report the progress to UI. You can optionally pass any values required to be accessed by UI elements. Dim progress As Integer = (i * 100) \ MAX BackgroundWorker1.ReportProgress(progress, i) ' check if user wants to cancel this task. If Yes, then quit. If BackgroundWorker1.CancellationPending Then e.Cancel = True Exit Sub End If Next End Sub Private Sub BackgroundWorker1_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged ProgressBar1.Value = e.ProgressPercentage TextBox1.Text = e.UserState.ToString End Sub Private Sub BackgroundWorker1_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted If e.Cancelled Then MessageBox.Show("Cancelled!") Else MessageBox.Show("Work done") End If End Sub
Run the program and first click Button1. It will start the background worker thread. Click Button2 anywhere in between to cancel it.
Last edited by Pradeep1210; Oct 25th, 2013 at 09:24 AM.
Reason: Corrected grammar and explained in detail.
-
Oct 24th, 2013, 09:28 PM
#6
Re: BackroundWorker Problem that I can't figure out
Why are you using a BackgroundWorker at all? It's pointless and quite wrong the way you're doing it. What are you actually trying to achieve? It's mind-boggling the number of people who ask for help and don't even tell us that. The whole point of using a BackgroundWorker is so that you DON'T have to do what .paul. is suggesting. It provides a model for multi-threading that involves just methods and events. If you're not using that model then you shouldn't be using a BackgroundWorker at all. So, explain what you're trying to achieve and then we might have a chance of explaining how to achieve it properly. Maybe it will involve a BackgroundWorker and maybe not. Maybe it will involve multi-threading and maybe not. The whole point of a BackgroundWorker is, as the name suggests, background work. Your DoWork event handler is accessing numerous UI elements so it is the very definition of foreground work, so the complete opposite of what it's for.
-
Oct 24th, 2013, 10:17 PM
#7
Re: BackroundWorker Problem that I can't figure out
@JM.
there are cases where accessing controls from a secondary thread is unavoidable.
BTW. I learned almost exactly that code from you in 2007
- Coding Examples:
- Features:
- Online Games:
- Compiled Games:
-
Oct 24th, 2013, 11:44 PM
#8
Re: BackroundWorker Problem that I can't figure out
Originally Posted by .paul.
@JM.
there are cases where accessing controls from a secondary thread is unavoidable.
BTW. I learned almost exactly that code from you in 2007
I didn't say that there was anything wrong with using delegation to access the UI from secondary threads. What I said was that the point of the BackgroundWorker was to perform the delegation for you so that you can just work with methods and events, which everyone's already familiar with anyway. That code is just bad use of a BackgroundWorker and adding lots of delegation is not the way to fix it. That code needs some real work.
-
Oct 25th, 2013, 06:43 AM
#9
Re: BackroundWorker Problem that I can't figure out
You might want to have a look at this codebank thread:
Correct way to use the BackgroundWorker
-
Oct 30th, 2013, 08:24 AM
#10
Thread Starter
Member
Re: BackroundWorker Problem that I can't figure out
Thanks for your help, I have removed all background worker elements in realising, this wasn't what they where to be used for.
What I wanted, was a way to interupt the loop once the report had started to generate. I have changed my program so it asks you if you want to continue after finishing each log file.
Tags for this Thread
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|