jerute
asked on
System.Threading.ThreadStateException error...?
Hi experts
I am lost when trying to understand why this error is being thrown. I wasn't aware I was using a worker thread in my code. Please could somebody help me understand what is happenning...
I have two forms, called for arguments sake 'Main' and 'Explorer'
When a button is clicked in 'Explorer' it calls a public sub in 'Main' called SendReceive() which executes, as the name suggests, a sendreceive in the outlook namespace. It also sets up a handler for the syncend() event, called private sub SyncEnd(). When this event is called it removes the handler, kills the outlook.exe process then calls a sub in the 'Explorer' form to refresh it's view of the folder.
It's this last call that throws the exception. I am left assuming that the synend handler is being run in a seperate thread. If that is so, how do i call back to the 'Explorer' Form?
See code below.
Any help is appreciated. Thanks in advance.
I am lost when trying to understand why this error is being thrown. I wasn't aware I was using a worker thread in my code. Please could somebody help me understand what is happenning...
I have two forms, called for arguments sake 'Main' and 'Explorer'
When a button is clicked in 'Explorer' it calls a public sub in 'Main' called SendReceive() which executes, as the name suggests, a sendreceive in the outlook namespace. It also sets up a handler for the syncend() event, called private sub SyncEnd(). When this event is called it removes the handler, kills the outlook.exe process then calls a sub in the 'Explorer' form to refresh it's view of the folder.
It's this last call that throws the exception. I am left assuming that the synend handler is being run in a seperate thread. If that is so, how do i call back to the 'Explorer' Form?
See code below.
Any help is appreciated. Thanks in advance.
'
' Main routines
'
Public Sub SendReceive()
Try
oApp = New Outlook.Application
Dim oNS As Outlook._NameSpace = oApp.GetNamespace("mapi")
Dim oSyncs As Outlook.SyncObjects
Dim oSync As Outlook.SyncObject
oNS.Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox).GetExplorer()
oSyncs = oNS.SyncObjects
oSync = oSyncs.Item("All Accounts")
instance = oSync
AddHandler instance.SyncEnd, AddressOf SyncEnd
oSync.Start()
oNS.Logoff()
oSync = Nothing
oSyncs = Nothing
oNS = Nothing
oApp = Nothing
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Sub
Private Sub SyncEnd()
RemoveHandler instance.SyncEnd, AddressOf SyncEnd
oApp = Nothing
Dim myProcesses As Process() = Process.GetProcessesByName("outlook")
For Each myProcess As Process In myProcesses
If myProcess.MainWindowTitle = "" Then myProcess.Kill()
Next myProcess
If Explorer.Visible = True Then Explorer.RefreshItems()
End Sub
'
' Explorer routines
'
Private Sub SendReceive(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tssendreceive.Click
main.SendReceive()
End Sub
Public Sub RefreshItems()
Dim session As RDOSession = CreateObject("Redemption.RDOSession")
session.Logon()
folderitems = GetMailItemsFromFolder(session.GetFolderFromPath(currentfolder))
UpdateItems(SelectRows(sortcolumn & " " & sortorder))
session.Logoff()
End Sub
ASKER
Hi wmestrom
Thanks for your reply but I'm not sure if this would work. I neglected to mention that the explorer form remains open while the sendreceive runs.
Therefore the line 'dim explorerform as system.windows.forms.form' is going to cause a second instance, isn't it?
Jerute
Thanks for your reply but I'm not sure if this would work. I neglected to mention that the explorer form remains open while the sendreceive runs.
Therefore the line 'dim explorerform as system.windows.forms.form'
Jerute
Hi jerute,
it will only create a instance if you assign it a 'New ExplorerForm' (or whatever name you gave it). However you can also just use a reference to your already open form (the Explorer variable in your code that is I think).
Just note that the method will only be called when the window is handling messages. Put simply, when it is responding to clicks, it will also execute methods send to it using Invoke().
I hope this answers your questions.
Willem
it will only create a instance if you assign it a 'New ExplorerForm' (or whatever name you gave it). However you can also just use a reference to your already open form (the Explorer variable in your code that is I think).
Just note that the method will only be called when the window is handling messages. Put simply, when it is responding to clicks, it will also execute methods send to it using Invoke().
I hope this answers your questions.
Willem
ASKER
As clear as mud. I am sorry wmestrom but when it comes to delegates I am, in the official terminology, an idiot. I really don't understand them.
Which of these bits goes where?
Thanks for your patience
Jerute
Which of these bits goes where?
Thanks for your patience
Jerute
Hi Jerute,
I copied your code and if I understand it correctly you just have to change two things. I added a delegate definition and changed the call to the RefreshItems method. This should do the trick.
Willem
I copied your code and if I understand it correctly you just have to change two things. I added a delegate definition and changed the call to the RefreshItems method. This should do the trick.
Willem
'
' Main routines
'
Public Sub SendReceive()
Try
oApp = New Outlook.Application
Dim oNS As Outlook._NameSpace = oApp.GetNamespace("mapi")
Dim oSyncs As Outlook.SyncObjects
Dim oSync As Outlook.SyncObject
oNS.Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox).GetExplorer()
oSyncs = oNS.SyncObjects
oSync = oSyncs.Item("All Accounts")
instance = oSync
AddHandler instance.SyncEnd, AddressOf SyncEnd
oSync.Start()
oNS.Logoff()
oSync = Nothing
oSyncs = Nothing
oNS = Nothing
oApp = Nothing
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Sub
'ADDED: Define a delegate
Public Delegate Sub Refresh()
Private Sub SyncEnd()
RemoveHandler instance.SyncEnd, AddressOf SyncEnd
oApp = Nothing
Dim myProcesses As Process() = Process.GetProcessesByName("outlook")
For Each myProcess As Process In myProcesses
If myProcess.MainWindowTitle = "" Then myProcess.Kill()
Next myProcess
If Explorer.Visible = True Then
'CHANGED: Use Invoke instead of a direct call
Explorer.Invoke([Delegate].CreateDelegate(GetType(RefreshDelegate), Explorer, "RefreshItems"))
End If
End Sub
'
' Explorer routines
'
Private Sub SendReceive(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tssendreceive.Click
Main.SendReceive()
End Sub
Public Sub RefreshItems()
Dim session As RDOSession = CreateObject("Redemption.RDOSession")
session.Logon()
folderitems = GetMailItemsFromFolder(session.GetFolderFromPath(currentfolder))
UpdateItems(SelectRows(sortcolumn & " " & sortorder))
session.Logoff()
End Sub
ASKER
No, doesn't work. I have an issue with your code, and this may be the problem. I refer to the line
Explorer.Invoke([Delegate] .CreateDel egate(GetT ype(Refres hDelegate) , Explorer, "RefreshItems"))
My IntelliSense tells me that refreshdelegate is not defined. I assumed (maybe incorrectly) that this should be the same as the
Public Delegate Sub Refresh()
which, incidentally, I have had to change due to it being the same as form.refresh. Lets assume, for arguments sake, that I have put
Public Delegate Sub RefreshView().
One way or another I am still getting the exceptions thrown by this call...
A first chance exception of type 'System.Threading.ThreadSt ateExcepti on' occurred in System.Windows.Forms.dll
A first chance exception of type 'System.InvalidOperationEx ception' occurred in wbcontrol.exe
I'm glad you are more patient than me. LOL. Thank you.
Explorer.Invoke([Delegate]
My IntelliSense tells me that refreshdelegate is not defined. I assumed (maybe incorrectly) that this should be the same as the
Public Delegate Sub Refresh()
which, incidentally, I have had to change due to it being the same as form.refresh. Lets assume, for arguments sake, that I have put
Public Delegate Sub RefreshView().
One way or another I am still getting the exceptions thrown by this call...
A first chance exception of type 'System.Threading.ThreadSt
A first chance exception of type 'System.InvalidOperationEx
I'm glad you are more patient than me. LOL. Thank you.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
I don't use sub main(), so where should this go?
my entry point is form_load...
my entry point is form_load...
ASKER
oh, and
thread.SetApartmentState(T hreading.A partmentSt ate.STA)
isn't recognised by intellisense...
thread.SetApartmentState(T
isn't recognised by intellisense...
ASKER
but
thread.CurrentThread.SetAp artmentSta te(Threadi ng.Apartme ntState.ST A)
is. It didn't, however, solve the problem.
:(
I hate losing...
thread.CurrentThread.SetAp
is. It didn't, however, solve the problem.
:(
I hate losing...
ASKER
Hi wmestrom
Although I still haven't found a solution to this problem I have assigned the points to you for your participation.
Thanks again.
Although I still haven't found a solution to this problem I have assigned the points to you for your participation.
Thanks again.
Open in new window