Asked by:
Having difficulty with Cross-Thread operation stuff

Question
-
All I want to do is use the OpenFileDialog to select a picture and then load it into a PictureBox in a form by editing the .imagelocation property. That's all; a very simple task. I wasn't trying to develop a multi-threaded application. I don't care how many threads are used, one is fine! Is there a way to just turn off Multi-threading in my application so that I can just develop as I've always done before? If not, well then I'm trying to do what is suggested in the following post:
But I don't know what to do in the BackgroundWorker1_DoWork procedure. I'm attempting to change the .imagelocation property only and display it. Do I really have to use a reader and constantly update it's progress as it reads the image? This doesn't make sense to me. Here's the code I have so far, please take a peak and tell me where I've gone wrong. Thank you kindly.
Imports System.Windows.Forms Imports System.IO Imports System.ComponentModel Public Class TaskPaneControl Private Sub cmdBrowse_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdBrowse.Click Dim fdlg As OpenFileDialog = New OpenFileDialog() fdlg.Title = "Picture Duplicator Open File Dialog" fdlg.InitialDirectory = "C:\" fdlg.Filter = "Image Files(*.BMP;*.JPG;*.GIF)|*.BMP;*.JPG;*.GIF|All files (*.*)|*.*" fdlg.FilterIndex = 2 fdlg.RestoreDirectory = True If fdlg.ShowDialog() = DialogResult.OK Then With Me.BackgroundWorker1 .WorkerReportsProgress = True .RunWorkerAsync(fdlg.FileName) End With End If End Sub Private Sub BackgroundWorker1_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork 'Dim filename As String = e.Argument 'Using reader As New StreamReader(filename) ' While Not reader.EndOfStream ' Me.BackgroundWorker1.ReportProgress(0.0, reader.ReadLine()) ' End While 'End Using End Sub Private Sub BackgroundWorker1_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged Me.pbPictureBox.ImageLocation = e.UserState End Sub Private Sub BackgroundWorker1_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted MsgBox("Done reading the file!") End Sub End Class
dyslexics of the world UNTIE!- Moved by Chao Kuo Friday, September 24, 2010 11:39 AM (From:Visual Basic General)
Saturday, September 18, 2010 2:37 AM
All replies
-
I would recommend dropping the BackgroundWorker stuff and just setting the Picturebox.ImageLocation property.
Dim fdlg As OpenFileDialog = New OpenFileDialog()
fdlg.Title = "Picture Duplicator Open File Dialog"
fdlg.InitialDirectory = "C:\"
fdlg.Filter = "Image Files(*.BMP;*.JPG;*.GIF)|*.BMP;*.JPG;*.GIF|All files (*.*)|*.*"
fdlg.FilterIndex = 2
fdlg.RestoreDirectory = True
If fdlg.ShowDialog() = DialogResult.OK Then
pbPictureBox.ImageLocation = fdlg.FileNameEnd If
--
Mike- Proposed as answer by Cor Ligthert Saturday, September 18, 2010 6:03 AM
Saturday, September 18, 2010 2:50 AM -
I would love to do that. In fact that's exactly the code I had in the beginning but that's when I got the error: InvalidOperationException was unhandled. Cross-thread operation not valid: Control 'TaskPaneControl' accessed from a thread other than the thread it was created on.
To further clarify what I'm doing the form is actually a custom task pane that I'm building for an Excel add-on using VSTO. I'm using Visual Studio 2008 and Excel 2007 for this add-on. But I wouldn't expect this custom task pane to be treated any differently than a basic form. Maybe I'm wrong here though.
dyslexics of the world UNTIE!Saturday, September 18, 2010 2:57 AM -
With the code you posted, I am not seeing any way that you would have gotten a cross-threading error. I don't do VSTO development, but that would seem like an odd behavior if that environment caused the issue.
--
MikeSaturday, September 18, 2010 3:03 AM -
I just duplicated the problem again and this time I copied the exception details to the clipboard and I've pasted them here. Is there anything in there that catches your eye?
System.InvalidOperationException was unhandledMessage="Cross-thread operation not valid: Control 'TaskPaneControl' accessed from a thread other than the thread it was created on."Source="System.Windows.Forms"StackTrace:at System.Windows.Forms.Control.get_Handle()at System.Windows.Forms.Control.get_InternalHandle()at System.Windows.Forms.Control.get_CreateParams()at System.Windows.Forms.PictureBox.get_CreateParams()at System.Windows.Forms.Control.SizeFromClientSize(Int32 width, Int32 height)at System.Windows.Forms.Control.SizeFromClientSize(Size clientSize)at System.Windows.Forms.PictureBox.GetPreferredSizeCore(Size proposedSize)at System.Windows.Forms.Control.GetPreferredSize(Size proposedSize)at System.Windows.Forms.Layout.DefaultLayout.xGetDockedSize(IArrangedElement element, Size remainingSize, Size constraints, Boolean measureOnly)at System.Windows.Forms.Layout.DefaultLayout.GetVerticalDockedSize(IArrangedElement element, Size remainingSize, Boolean measureOnly)at System.Windows.Forms.Layout.DefaultLayout.LayoutDockedControls(IArrangedElement container, Boolean measureOnly)at System.Windows.Forms.Layout.DefaultLayout.xLayout(IArrangedElement container, Boolean measureOnly, Size& preferredSize)at System.Windows.Forms.Layout.DefaultLayout.LayoutCore(IArrangedElement container, LayoutEventArgs args)at System.Windows.Forms.Layout.LayoutEngine.Layout(Object container, LayoutEventArgs layoutEventArgs)at System.Windows.Forms.Control.OnLayout(LayoutEventArgs levent)at System.Windows.Forms.ScrollableControl.OnLayout(LayoutEventArgs levent)at System.Windows.Forms.ContainerControl.OnLayout(LayoutEventArgs e)at System.Windows.Forms.Control.PerformLayout(LayoutEventArgs args)at System.Windows.Forms.Control.System.Windows.Forms.Layout.IArrangedElement.PerformLayout(IArrangedElement affectedElement, String affectedProperty)at System.Windows.Forms.Layout.LayoutTransaction.DoLayout(IArrangedElement elementToLayout, IArrangedElement elementCausingLayout, String property)at System.Windows.Forms.Control.PerformLayout(LayoutEventArgs args)at System.Windows.Forms.Control.System.Windows.Forms.Layout.IArrangedElement.PerformLayout(IArrangedElement affectedElement, String affectedProperty)at System.Windows.Forms.Layout.LayoutTransaction.DoLayout(IArrangedElement elementToLayout, IArrangedElement elementCausingLayout, String property)at System.Windows.Forms.Layout.LayoutTransaction.DoLayoutIf(Boolean condition, IArrangedElement elementToLayout, IArrangedElement elementCausingLayout, String property)at System.Windows.Forms.PictureBox.InstallNewImage(Image value, ImageInstallationType installationType)at System.Windows.Forms.PictureBox.LoadCompletedDelegate(Object arg)at System.Threading._ThreadPoolWaitCallback.WaitCallback_Context(Object state)at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)at System.Threading._ThreadPoolWaitCallback.PerformWaitCallbackInternal(_ThreadPoolWaitCallback tpWaitCallBack)at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback(Object state)InnerException:
dyslexics of the world UNTIE!Saturday, September 18, 2010 3:06 AM -
Here's an interesting little development in my problem. Just a minute ago I closed Visual Studio and then just went into Excel to work on a file and I found that my add-on was installed on the ribbon. even though I hadn't compiled it or anything. I decided to give it a try and this time it actually loaded the picture into the picturebox as I've been wanting. If I go back into visual studio and open the solution again i get the same Cross-Threading error as before. I added the statement, "on error resume next" and that didn't fix it. Strange how this will work when running it in Excel but not while running it in debug mode in Visual Studio.
dyslexics of the world UNTIE!Saturday, September 18, 2010 3:59 AM -
If you don't know why you use a background worker, then don't use it, it gives then only overhead.
Although it is quite interesting to tell that you have a program that runs in multithreads, is that often the only reason persons use it.
For everything in programming you need a reason, and especially for an extra thread.
So use the first sample from Mike.
If in that sample multithreading is used, then the only reason for that is that you have used multithreading, it will for make the processing time longer.
Success
CorSaturday, September 18, 2010 6:03 AM -
I couldn't agree with you more. It would certainly make this project easier if I could use Mike's example. As a matter of fact I am using Mike's example but I am getting the error above. I'm not intentionally trying to use multithreading. Could you tell me how it is that I am using multithreading? How do I stop using multithreading? Is there a setting that I have inadvertently enabled that is causing it to use multithreading?
dyslexics of the world UNTIE!Saturday, September 18, 2010 6:11 AM -
Mike has done that already in his first reply,
To be sure I tested it even.
Public Class Form1 Private Sub cmdBrowse_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdBrowse.Click Dim fdlg As OpenFileDialog = New OpenFileDialog() fdlg.Title = "Picture Duplicator Open File Dialog" fdlg.InitialDirectory = "C:\" fdlg.Filter = "Image Files(*.BMP;*.JPG;*.GIF)|*.BMP;*.JPG;*.GIF|All files (*.*)|*.*" fdlg.FilterIndex = 2 fdlg.RestoreDirectory = True If fdlg.ShowDialog() = DialogResult.OK Then pbPictureBox.ImageLocation = fdlg.FileName End If End Sub End Class
If you mark this as answer, then don't forget the answer in Mike's first reply.
Success
CorSaturday, September 18, 2010 6:40 AM -
A cross thread error is just that. It is when data or a control is give to a different execution thread. Most of the time it's to keep threads contained. There are a few exceptions to this like .invoke an operation called for many kinds of threads.
Renee
Saturday, September 18, 2010 7:19 AM -
Okay, I have copied and pasted the code that has been provided. But I am still receiving the cross-thread error. I understand now what a cross-thread error is and I understand that I should not be using multithreading. Why then am I still receiving the error after using the code provided? Could someone tell me what else I could be doing wrong besides using the provided code to receive the error? If you guys aren't getting that error when you use the code and I am then I don't believe the code is the culprit. It's got to be something else I've done wrong, maybe a setting in my configuration somewhere.
Do I need to use the .invoke operation instead? if so, how would I use it?
dyslexics of the world UNTIE!Saturday, September 18, 2010 3:21 PM -
Is there any possibility that you are launching the form containing the TaskPaneControl in a background worker?
--
MikeSaturday, September 18, 2010 3:53 PM -
Never mind... That was an obsurd thought...
--
MikeSaturday, September 18, 2010 3:54 PM -
I'm getting the error even when I'm just using this:
I've removed the background worker.Public Class PictureDuplicatorActionsPane Private Sub btnBrowse_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnBrowse.Click Me.pbPictureBox.ImageLocation = Me.txtPath.Text End Sub End Class
dyslexics of the world UNTIE!Saturday, September 18, 2010 3:59 PM -
Put a messagebox in your code before the me.pbPicturebox line. This will see if you are even using the correct code in your test.
--
MikeSaturday, September 18, 2010 4:05 PM -
okay, I just created a new project and chose Windows Forms Application as the template. I then just added a picturebox, a textbox and a button and then added the code below. It worked fine. I didnt' get the cross-thread error. So, this has got to be related to using a picturbox control in a custom task pane in VSTO for an Excel 2007 Workbook or Add-in (I've attempted both). I'm going to refer to the VSTO forums instead for this problem. It has to be a VSTO issue.
Public Class Form1 Private Sub Button1_Click_1(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim fdlg As OpenFileDialog = New OpenFileDialog fdlg.Title = "Picture Duplicator Open File Dialog" fdlg.InitialDirectory = "C:\" fdlg.Filter = "Image Files(*.BMP;*.JPG;*.GIF)|*.BMP;*.JPG;*.GIF|All files (*.*)|*.* " fdlg.FilterIndex = 1 fdlg.RestoreDirectory = True If fdlg.ShowDialog() = DialogResult.OK Then Me.PictureBox1.ImageLocation = fdlg.FileName Me.TextBox1.Text = fdlg.FileName End If End Sub End Class
dyslexics of the world UNTIE!Saturday, September 18, 2010 4:09 PM