locked
Having difficulty with Cross-Thread operation stuff RRS feed

  • 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:

    http://social.msdn.microsoft.com/Forums/en-US/vbgeneral/thread/f41bb09a-e13d-46db-a9ec-2958d7415eb3?prof=required

    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.FileName
        End 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.

    --
    Mike
    Saturday, 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 unhandled
      Message="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
    Cor
    Saturday, 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
    Cor
    Saturday, 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?

    --
    Mike
    Saturday, September 18, 2010 3:53 PM

  • Never mind...  That was an obsurd thought...

    --
    Mike
    Saturday, September 18, 2010 3:54 PM
  • I'm getting the error even when I'm just using this:

    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
    
    I've removed the background worker.


    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.

    --
    Mike
    Saturday, 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