Santor

I copied and modified a Filewatcher program from the web and it works fine but I get this error...

"Cross-thread operation not valid: Control 'lstEvents' accessed from a thread other than the thread it was created on."

I've spent hours researching and trying to fix this but I just dont know enough yet to get it.

I've read its as simple as setting the filesystemwatcher SynchronizingObject property to the listbox but I dont even know how to do that yet.

Could someone please give me some specific instructions on how to correct this error

Thanks

John

Imports System

Imports System.IO

Imports System.Text

Imports System.Diagnostics

Imports System.Data.OleDb

Imports System.Globalization

Imports System.Threading

Imports System.Windows.Forms

Imports Microsoft.Office.Core

Imports excel = Microsoft.Office.Interop.excel

'

Public Class Form1

Inherits System.Windows.Forms.Form

Public watchfolder As FileSystemWatcher

#Region " Windows Form Designer generated code "

Public Sub New()

MyBase.New()

'This call is required by the Windows Form Designer.

InitializeComponent()

'Add any initialization after the InitializeComponent() call

End Sub

'Form overrides dispose to clean up the component list.

Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)

If disposing Then

If Not (components Is Nothing) Then

components.Dispose()

End If

End If

MyBase.Dispose(disposing)

End Sub

'Required by the Windows Form Designer

Private components As System.ComponentModel.IContainer

'NOTE: The following procedure is required by the Windows Form Designer

'It can be modified using the Windows Form Designer.

'Do not modify it using the code editor.

Friend WithEvents Label1 As System.Windows.Forms.Label

Friend WithEvents txt_watchpath As System.Windows.Forms.TextBox

Friend WithEvents Label2 As System.Windows.Forms.Label

Friend WithEvents btn_startwatch As System.Windows.Forms.Button

Friend WithEvents btn_stop As System.Windows.Forms.Button

Friend WithEvents Button1 As System.Windows.Forms.Button

Friend WithEvents FolderBrowserDialog1 As System.Windows.Forms.FolderBrowserDialog

Friend WithEvents chkIncludeSubdirs As System.Windows.Forms.CheckBox

Friend WithEvents Label3 As System.Windows.Forms.Label

Friend WithEvents XL_file As System.Windows.Forms.TextBox

Friend WithEvents lstEvents As System.Windows.Forms.ListBox

Friend WithEvents Label4 As System.Windows.Forms.Label

Friend WithEvents FileSystemWatcher1 As System.IO.FileSystemWatcher

Friend WithEvents XL_file_copy As System.Windows.Forms.TextBox

<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()

Me.Label1 = New System.Windows.Forms.Label

Me.txt_watchpath = New System.Windows.Forms.TextBox

Me.Label2 = New System.Windows.Forms.Label

Me.btn_startwatch = New System.Windows.Forms.Button

Me.btn_stop = New System.Windows.Forms.Button

Me.Button1 = New System.Windows.Forms.Button

Me.FolderBrowserDialog1 = New System.Windows.Forms.FolderBrowserDialog

Me.chkIncludeSubdirs = New System.Windows.Forms.CheckBox

Me.Label3 = New System.Windows.Forms.Label

Me.XL_file = New System.Windows.Forms.TextBox

Me.lstEvents = New System.Windows.Forms.ListBox

Me.Label4 = New System.Windows.Forms.Label

Me.XL_file_copy = New System.Windows.Forms.TextBox

Me.FileSystemWatcher1 = New System.IO.FileSystemWatcher

CType(Me.FileSystemWatcher1, System.ComponentModel.ISupportInitialize).BeginInit()

Me.SuspendLayout()

'

'Label1

'

Me.Label1.Location = New System.Drawing.Point(16, 16)

Me.Label1.Name = "Label1"

Me.Label1.Size = New System.Drawing.Size(88, 16)

Me.Label1.TabIndex = 0

Me.Label1.Text = "Folder to watch:"

'

'txt_watchpath

'

Me.txt_watchpath.Location = New System.Drawing.Point(104, 16)

Me.txt_watchpath.Name = "txt_watchpath"

Me.txt_watchpath.Size = New System.Drawing.Size(256, 20)

Me.txt_watchpath.TabIndex = 1

Me.txt_watchpath.Text = "d:\RADCO"

'

'Label2

'

Me.Label2.Location = New System.Drawing.Point(16, 128)

Me.Label2.Name = "Label2"

Me.Label2.Size = New System.Drawing.Size(96, 16)

Me.Label2.TabIndex = 3

Me.Label2.Text = "Folder Activity"

'

'btn_startwatch

'

Me.btn_startwatch.Location = New System.Drawing.Point(376, 16)

Me.btn_startwatch.Name = "btn_startwatch"

Me.btn_startwatch.Size = New System.Drawing.Size(104, 24)

Me.btn_startwatch.TabIndex = 4

Me.btn_startwatch.Text = "Start Watching"

'

'btn_stop

'

Me.btn_stop.Location = New System.Drawing.Point(376, 48)

Me.btn_stop.Name = "btn_stop"

Me.btn_stop.Size = New System.Drawing.Size(104, 24)

Me.btn_stop.TabIndex = 5

Me.btn_stop.Text = "Stop Watching"

'

'Button1

'

Me.Button1.Location = New System.Drawing.Point(104, 40)

Me.Button1.Name = "Button1"

Me.Button1.Size = New System.Drawing.Size(75, 23)

Me.Button1.TabIndex = 7

Me.Button1.Text = "Browse"

'

'chkIncludeSubdirs

'

Me.chkIncludeSubdirs.Checked = True

Me.chkIncludeSubdirs.CheckState = System.Windows.Forms.CheckState.Checked

Me.chkIncludeSubdirs.Location = New System.Drawing.Point(224, 40)

Me.chkIncludeSubdirs.Name = "chkIncludeSubdirs"

Me.chkIncludeSubdirs.Size = New System.Drawing.Size(136, 24)

Me.chkIncludeSubdirs.TabIndex = 8

Me.chkIncludeSubdirs.Text = "Include Subdirectories"

'

'Label3

'

Me.Label3.Location = New System.Drawing.Point(16, 80)

Me.Label3.Name = "Label3"

Me.Label3.Size = New System.Drawing.Size(176, 16)

Me.Label3.TabIndex = 9

Me.Label3.Text = "Master Excel file path and name:"

'

'XL_file

'

Me.XL_file.Location = New System.Drawing.Point(184, 80)

Me.XL_file.Name = "XL_file"

Me.XL_file.Size = New System.Drawing.Size(296, 20)

Me.XL_file.TabIndex = 10

Me.XL_file.Text = "d:\watch radco folder\RADCO_log.xls"

'

'lstEvents

'

Me.lstEvents.Anchor = System.Windows.Forms.AnchorStyles.None

Me.lstEvents.IntegralHeight = False

Me.lstEvents.Location = New System.Drawing.Point(16, 142)

Me.lstEvents.Name = "lstEvents"

Me.lstEvents.ScrollAlwaysVisible = True

Me.lstEvents.Size = New System.Drawing.Size(464, 162)

Me.lstEvents.TabIndex = 11

'

'Label4

'

Me.Label4.Location = New System.Drawing.Point(56, 104)

Me.Label4.Name = "Label4"

Me.Label4.Size = New System.Drawing.Size(120, 16)

Me.Label4.TabIndex = 12

Me.Label4.Text = "User copy of Excel file:"

'

'XL_file_copy

'

Me.XL_file_copy.Location = New System.Drawing.Point(184, 104)

Me.XL_file_copy.Name = "XL_file_copy"

Me.XL_file_copy.Size = New System.Drawing.Size(296, 20)

Me.XL_file_copy.TabIndex = 13

Me.XL_file_copy.Text = "d:\RADCO\RADCO_log.xls"

'

'FileSystemWatcher1

'

Me.FileSystemWatcher1.EnableRaisingEvents = True

Me.FileSystemWatcher1.SynchronizingObject = Me

'

'Form1

'

Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)

Me.ClientSize = New System.Drawing.Size(496, 317)

Me.Controls.Add(Me.XL_file_copy)

Me.Controls.Add(Me.Label4)

Me.Controls.Add(Me.lstEvents)

Me.Controls.Add(Me.XL_file)

Me.Controls.Add(Me.Label3)

Me.Controls.Add(Me.chkIncludeSubdirs)

Me.Controls.Add(Me.Button1)

Me.Controls.Add(Me.btn_stop)

Me.Controls.Add(Me.btn_startwatch)

Me.Controls.Add(Me.Label2)

Me.Controls.Add(Me.txt_watchpath)

Me.Controls.Add(Me.Label1)

Me.Name = "Form1"

Me.Text = "Folder Watch"

CType(Me.FileSystemWatcher1, System.ComponentModel.ISupportInitialize).EndInit()

Me.ResumeLayout(False)

Me.PerformLayout()

End Sub

#End Region

'

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

If FolderBrowserDialog1.ShowDialog() = Windows.Forms.DialogResult.OK Then

txt_watchpath.Text = FolderBrowserDialog1.SelectedPath

End If

End Sub

'

Private Sub btn_startwatch_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btn_startwatch.Click

watchfolder = New System.IO.FileSystemWatcher

'this is the path we want to monitor

watchfolder.Path = txt_watchpath.Text

' Include subdirectories if box checked

If chkIncludeSubdirs.CheckState = CheckState.Checked Then

watchfolder.IncludeSubdirectories = True

End If

If chkIncludeSubdirs.CheckState = CheckState.Unchecked Then

watchfolder.IncludeSubdirectories = False

End If

Dim XLFileCopy As String = XL_file_copy.Text

Dim XLFile As String = XL_file.Text

If File.Exists(XLFile) Then

'Add a list of Filter we want to specify

'make sure you use OR for each Filter as we need to

'all of those

watchfolder.NotifyFilter = IO.NotifyFilters.DirectoryName

watchfolder.NotifyFilter = watchfolder.NotifyFilter Or _

IO.NotifyFilters.FileName

watchfolder.NotifyFilter = watchfolder.NotifyFilter Or _

IO.NotifyFilters.Attributes

' Only watch for PDF files.

watchfolder.Filter = "*.pdf"

' add the handler to each event

' AddHandler watchfolder.Changed, AddressOf logchange

AddHandler watchfolder.Created, AddressOf logchangeAdd

AddHandler watchfolder.Deleted, AddressOf logchangeDel

' add the rename handler as the signature is different

AddHandler watchfolder.Renamed, AddressOf logrename

'Set this property to true to start watching

watchfolder.EnableRaisingEvents = True

btn_startwatch.Enabled = False

btn_stop.Enabled = True

'

' Types of changes that can be watched for:

' Attributes (The attributes of the file or folder)

' CreationTime (The time the file or folder was created)

' DirectoryName (The name of the directory)

' FileName (The name of the file)

' LastAccess (The date the file or folder was last opened)

' LastWrite (The date the file or folder last had anything written to it)

' Security (The security settings of the file or folder)

' Size (The size of the file or folder)

Else

MessageBox.Show("Master Excel File Does Not Exist!")

End If

'End of code for btn_start_click

End Sub

Private Sub logchangeAdd(ByVal source As Object, ByVal e As _

System.IO.FileSystemEventArgs)

If e.ChangeType = IO.WatcherChangeTypes.Created Then

Dim strText As String = "File " & e.FullPath & " has been created"

AddItem(strText)

Add_Record(source, e)

End If

End Sub

Private Sub logchangeDel(ByVal source As Object, ByVal e As _

System.IO.FileSystemEventArgs)

If e.ChangeType = IO.WatcherChangeTypes.Deleted Then

Dim strText As String = "File " & e.FullPath & " has been deleted"

AddItem(strText)

Add_Record(source, e)

End If

End Sub

' Private Sub logchange(ByVal source As Object, ByVal e As _

' System.IO.FileSystemEventArgs)

' If e.ChangeType = IO.WatcherChangeTypes.Changed Then

' txt_folderactivity.Text = "File " & e.FullPath & _

' " has been modified"

' ' Add_Record(source, e)

' End If

' End Sub

'

Public Sub logrename(ByVal source As Object, ByVal e As _

System.IO.RenamedEventArgs)

Dim strText As String = "File" & e.OldName & " has been renamed to " & e.Name

AddItem(strText)

End Sub

'

Private Sub AddItem(ByVal strText As String)

lstEvents.Items.Add(strText)

End Sub

Private Sub btn_stop_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btn_stop.Click

watchfolder.EnableRaisingEvents = False

btn_startwatch.Enabled = True

btn_stop.Enabled = False

End Sub '

'

Private Sub Add_Record(ByVal source As Object, ByVal e As System.IO.FileSystemEventArgs)

Dim en As New CultureInfo("en-US")

Thread.CurrentThread.CurrentCulture = en

Dim uFile As String = e.Name

Dim TheDate As String = DateTime.Now

'

' Pull apart the uFile string which is the full path and file name into

' Folder, Plant and File name only. Path MUST BE Drive\Folder\Plant\File format.

Dim sFolder As String

Dim sPlant As String

Dim sFile As String

Dim iUpper As Integer

Dim PathPiece() As String = uFile.Split("\")

iUpper = UBound(PathPiece)

If iUpper < 2 Then

MsgBox("Improper directory structure in watched folder" & vbNewLine & "Structure MUST BE Drive\Folder\Plant\File")

End If

sFolder = PathPiece(iUpper - 2)

sPlant = PathPiece(iUpper - 1)

sFile = PathPiece(iUpper)

'

' The Excel file we want to write to

Dim XLFile As String = XL_file.Text

Dim XLFileCopy As String = XL_file_copy.Text

Dim XLSheet As String = sPlant

Dim sConnectionString As String = "Provider=Microsoft.Jet.OLEDB.4.0;" _

& "Data Source=" & XLFile _

& ";" & "Extended Properties=Excel 8.0;"

'

' This bit opens the spreadsheet, activates the worksheet then finds the actual used rows

' to try to make sure no empty rows show up due to a user manually deleting rows.

' if the empty rows will not go away then try opening the spreadsheet, select the rows,

' then edit, clear contents then delete the rows again.

'

Dim oExcel As excel.ApplicationClass

Dim oBook As excel.WorkbookClass

Dim oBooks As excel.Workbooks

oExcel = CreateObject("Excel.Application")

oExcel.Visible = False

oBooks = oExcel.Workbooks

oBook = oBooks.Open(XLFile)

Dim oSheet As excel.Worksheet

oSheet = oBook.Worksheets(XLSheet)

oSheet.Activate()

oBook.ActiveSheet.UsedRange()

'

oSheet = Nothing

oBook.Close(False)

System.Runtime.InteropServices.Marshal.ReleaseComObject(oBook)

oBook = Nothing

System.Runtime.InteropServices.Marshal.ReleaseComObject(oBooks)

oBooks = Nothing

oExcel.Quit()

System.Runtime.InteropServices.Marshal.ReleaseComObject(oExcel)

oExcel = Nothing

GC.Collect()

'

Dim Conn1 As New System.Data.OleDb.OleDbConnection(sConnectionString)

Conn1.Open()

Dim cmd As New System.Data.OleDb.OleDbCommand

cmd.Connection = Conn1

sPlant = String.Concat(sPlant, "$")

If String.Compare(sFolder, "pending", True) = 0 Then

cmd.CommandText = String.Format("INSERT INTO [{0}] (Project, Pending) VALUES(@au_file,@au_date)", sPlant)

Else

cmd.CommandText = String.Format("UPDATE [{0}] Set {1}='{2}' WHERE Project=sFile", sPlant, sFolder, TheDate)

End If

cmd.Parameters.AddWithValue("@au_file", sFile)

cmd.Parameters.AddWithValue("@au_date", TheDate)

cmd.ExecuteNonQuery()

Conn1.Close()

' Copy the XLFile so this program does not have to worry about a user keeping the master file open

System.IO.File.Copy(XLFile, XLFileCopy, True)

End Sub

End Class



Re: Visual Studio Debugger Plz help newbie with "Cross-thread operation not valid" error

Azeem Khan - MSFT

Santor,

Please refer to the following msdn article that talks about this issue.

http://msdn2.microsoft.com/en-us/library/ms171728.aspx

You need to use Invoke method. Note that this isn't really appropriate for this forum. Direct any further questions to a more appropriate forum.

Azeem Khan

VS Debugger