|
-
Dec 26th, 2006, 11:52 AM
#1
Thread Starter
Junior Member
[RESOLVED] [2005] Simple Threading Probloem
I'm trying to create a pretty easy threaded application but I keep getting an error message:
Cross-thread operation not valid: Control '' accessed from a thread other than the thread it was created on.
I am aware that I should only alter the properties of a control from the thread in which it was created on, but I'm not altering the control directly from another thread. This is my current source:
VB Code:
Imports System.IO
Imports System.Threading
Public Class MainForm
Private WithEvents _pdfMaker As PDFMaker
Private Sub btnBrowse_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnBrowse.Click
If (browseDialog.ShowDialog = Windows.Forms.DialogResult.OK) Then
txtArchiveFilePath.Text = browseDialog.FileName
End If
End Sub
Private Sub btnBurnFiles_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnBurnFiles.Click
_pdfMaker = New PDFMaker
Dim mainThread As Thread = New Thread(AddressOf _pdfMaker.createPdfFromTiffArchive)
_pdfMaker.ArchivePath = txtArchiveFilePath.Text
_pdfMaker.TempDir = "C:\test\"
mainThread.Start()
End Sub
Private Sub _pdfMaker_TiffAdded(ByVal percentDone As Double) Handles _pdfMaker.TiffAdded
currentProgress.Value = percentDone
txtStatus.Text = "Building PDF File (" & percentDone & "%)"
End Sub
End Class
The error message is coming from currentProgress.Value = percentDone. currentProgress is an object of type toolStripProgressBar. For some reason though if i comment that line out the next line: txtStatus.Text = "Building PDF File (" & percentDone & "%)" does not trigger an error... any ideas?
-
Dec 26th, 2006, 01:13 PM
#2
Re: [2005] Simple Threading Probloem
I wouldn't do it that way.
Create a sepparate class to handle the pdfmaker
That creates a new instance of Pdfmaker on creation
and contains a Sub that does the stuff you want it to do (let's call it DoIt).
for testing just create the class and test if the code is working
to run it on a sepparate thread do it something like this
Code:
Dim ClsPdf As New PdfClass
Dim T as Thread
T = New Thread(AddressOf ClsPdf.DoIt)
T.Start()
Added bonus is the possibility to safely get data from the thread to your main
program by adding Public Fields in the class like
Public TiffCreationComplete As Boolean
You can check in your main program to see if a certain stage in the sepperate thread has been accomplished.
 why can't programmers keep and 31 Oct and 25 dec apart. Why Rating is Useful
for every question you ask provide an answer on another thread.
-
Dec 26th, 2006, 02:31 PM
#3
Thread Starter
Junior Member
Re: [2005] Simple Threading Probloem
Thank you for your response, I'm still a little stuck though. The basic jist of my program is that it's taking in a .zip archive full of tiff files, breaking the the tiff files down into individual frames, and then packing all those frames into a PDF document.
I've tried to encapsulate that proccess into the "createPdfFromTiffArchive" subroutine within the "PDFMaker" class. The createPdfFromTiffArchive souroutine raises an event, "TiffAdded", everytime a Tiff file has been extracted and added to the PDF file.
I figured that by encapsulating all the statements needed to to create the PDF file in a single subroutine that i could call this subroutine in a seperate thread and have it run in the backround. That way i could just update the progress bar, "currentProgress", everytime the "tiffAdded" event is raised. I keep getting this cross-thread exception though.
I figured that the subroutine that handled the "tiffAdded" event was in the same thread that created "currentProgress." Am i wrong in this?
Are you sugesting that i create a second thread to monitor the status of my other thread?
-
Dec 26th, 2006, 07:00 PM
#4
Re: [2005] Simple Threading Probloem
You have two choices in VB2005 to avoid cross-thread control accesses. You can either use a BackgroundWorker instead of explicitly creating the worker thread. Then you can call the ReportProgress method to raise the ProgressChanged event in the UI thread rather than the worker. This means that the ProgressChanged event handler is executed in the UI thread so you can access controls directly. Alternatively you can use delegation to marshal your control accesses to the UI thread. Here's an example, and ther are many others posted on the forum already.
VB Code:
Private Delegate Sub SetTextBoxTextDelegate(ByVal text As String)
Private Sub SetTextBoxText(ByVal text As String)
If Me.TextBox1.InvokeRequired Then
'This is a worker thread so create a delegate to cross the thread boundary.
Me.TextBox1.Invoke(New SetTextBoxTextDelegate(AddressOf SetTextBoxText), text)
Else
'This is the UI thread so access the control's members directly.
Me.TextBox1.Text = text
End If
End Sub
-
Dec 26th, 2006, 07:13 PM
#5
Junior Member
Re: [2005] Simple Threading Probloem
-
Dec 27th, 2006, 09:37 AM
#6
Thread Starter
Junior Member
Re: [2005] Simple Threading Probloem
Thanks to both of you, I have it working right now. It took me forever and a day to figure out that you needed to call the invokeRequired method on the ProgressBar class that was encapsulated in the ToolStripProgressBar class. Here is the code if anyone is intrested:
VB Code:
Imports System.IO
Imports System.Threading
Public Class MainForm
Private Delegate Sub setProgressBarDelegate(ByVal value As Double)
Private WithEvents _pdfMaker As PDFMaker
Private Sub btnBrowse_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnBrowse.Click
If (browseDialog.ShowDialog = Windows.Forms.DialogResult.OK) Then
txtArchiveFilePath.Text = browseDialog.FileName
End If
End Sub
Private Sub btnBurnFiles_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnBurnFiles.Click
_pdfMaker = New PDFMaker
Dim mainThread As Thread = New Thread(AddressOf _pdfMaker.createPdfFromTiffArchive)
_pdfMaker.ArchivePath = txtArchiveFilePath.Text
_pdfMaker.TempDir = "C:\test\"
mainThread.Start()
End Sub
Private Sub _pdfMaker_TiffAdded(ByVal percentDone As Double) Handles _pdfMaker.TiffAdded
setProgressBar(percentDone)
txtStatus.Text = "Building PDF File (" & percentDone & "%)"
End Sub
Private Sub setProgressBar(ByVal value As Double)
If Me.currentProgress.ProgressBar.InvokeRequired Then
Me.currentProgress.ProgressBar.Invoke(New setProgressBarDelegate(AddressOf setProgressBar), value)
Else
Me.currentProgress.ProgressBar.Value = value
End If
End Sub
End Class
@I87
You can find some general information on threading here : . Basically it's a way to make the CPU do two or more things at once by switching rapidly between differnt tasks.
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
|