![]() |
If this is your first visit, be sure to check out the FAQ by clicking the link above. You may have to register before you can post: click the register link above to proceed. To start viewing messages, select the forum that you want to visit from the selection below. |
|
|
Thread Tools | Search this Thread | Display Modes |
|
#1
|
|||
|
|||
![]()
I've looked over a few posts on multi threading with the OOM and I understand
that the OOM itself is restricted to being single threaded. I could use some information on how this works. What I currently have is a MailItem object being passed to a new background thread every time an event occurs (Explorer.SelectionChange for example). In the thread I access things like SenderEmailAddress, ReplyRecipients. Is this thread safe? What happens if I access a OOM object from the worker thread that wasn't explicitly passed to it (Example: changing the visibility of a button on a ribbon bar). I'm guessing this isn't thread safe. Is there any way to trigger an event on the main thread once the worker thread has finished running? I am used to doing this with forms, and having a worker thread invoke a delegate on the main form. Since we're not working with forms, or even controls for that matter, how would I go about doing this? |
#2
|
|||
|
|||
![]()
Using the Outlook object model from anywhere but your main thread, without
marshaling calls to the object model back to that thread, is a great way to crash or hang Outlook. You really shouldn't be passing an Outlook object to the background thread. What you should do is set up a struct or something with the properties you need from that Outlook object and passing the struct to your background worker thread. That way all calls to the object model are done from the main thread. I use delegate event handlers in my main code to receive events fired by the worker thread when the work is finished. -- Ken Slovak [MVP - Outlook] http://www.slovaktech.com Author: Professional Programming Outlook 2007. Reminder Manager, Extended Reminders, Attachment Options. http://www.slovaktech.com/products.htm "Dorian" wrote in message news ![]() I've looked over a few posts on multi threading with the OOM and I understand that the OOM itself is restricted to being single threaded. I could use some information on how this works. What I currently have is a MailItem object being passed to a new background thread every time an event occurs (Explorer.SelectionChange for example). In the thread I access things like SenderEmailAddress, ReplyRecipients. Is this thread safe? What happens if I access a OOM object from the worker thread that wasn't explicitly passed to it (Example: changing the visibility of a button on a ribbon bar). I'm guessing this isn't thread safe. Is there any way to trigger an event on the main thread once the worker thread has finished running? I am used to doing this with forms, and having a worker thread invoke a delegate on the main form. Since we're not working with forms, or even controls for that matter, how would I go about doing this? |
#3
|
|||
|
|||
![]()
Using a struct for the MailItem information makes sense, and if I am able to,
using a delegate event handler to return to the main thread makes sense. In my previous experiences I've used the Invoke method of the control that the main thread is being run on. Unfortunately I don't use any forms in the my addin. Any hints on how to invoke an event on a main thread without having access to Control.Invoke? "Ken Slovak - [MVP - Outlook]" wrote: Using the Outlook object model from anywhere but your main thread, without marshaling calls to the object model back to that thread, is a great way to crash or hang Outlook. You really shouldn't be passing an Outlook object to the background thread. What you should do is set up a struct or something with the properties you need from that Outlook object and passing the struct to your background worker thread. That way all calls to the object model are done from the main thread. I use delegate event handlers in my main code to receive events fired by the worker thread when the work is finished. -- Ken Slovak [MVP - Outlook] http://www.slovaktech.com Author: Professional Programming Outlook 2007. Reminder Manager, Extended Reminders, Attachment Options. http://www.slovaktech.com/products.htm "Dorian" wrote in message news ![]() I've looked over a few posts on multi threading with the OOM and I understand that the OOM itself is restricted to being single threaded. I could use some information on how this works. What I currently have is a MailItem object being passed to a new background thread every time an event occurs (Explorer.SelectionChange for example). In the thread I access things like SenderEmailAddress, ReplyRecipients. Is this thread safe? What happens if I access a OOM object from the worker thread that wasn't explicitly passed to it (Example: changing the visibility of a button on a ribbon bar). I'm guessing this isn't thread safe. Is there any way to trigger an event on the main thread once the worker thread has finished running? I am used to doing this with forms, and having a worker thread invoke a delegate on the main form. Since we're not working with forms, or even controls for that matter, how would I go about doing this? |
#4
|
|||
|
|||
![]()
Something like this for the delegate events:
// In the class for the background worker: internal delegate void HelloUserDoneEventHandler(object sender, EventArgs e); internal event HelloUserDoneEventHandler HelloUserDone; // make a call in the code that handles worker done to OnHelloUserDone() protected virtual void OnHelloUserDone(EventArgs e) { HelloUserDoneEventHandler handler = HelloUserDone; if (handler != null) { // Invokes the delegate. handler(this, e); } } // in the code in the main class or wherever private void HelloUser(object sender, EventArgs e) { if (e.Result != null) { // event fired, work done } } Of course in the main code you'd need to instantiate the HelloUser event handler, something like this, where myWorker is the class that has the background worker: _worker.HelloUserDone += new myWorker.HelloUserDoneEventHandler(HelloUser); -- Ken Slovak [MVP - Outlook] http://www.slovaktech.com Author: Professional Programming Outlook 2007. Reminder Manager, Extended Reminders, Attachment Options. http://www.slovaktech.com/products.htm "Dorian" wrote in message ... Using a struct for the MailItem information makes sense, and if I am able to, using a delegate event handler to return to the main thread makes sense. In my previous experiences I've used the Invoke method of the control that the main thread is being run on. Unfortunately I don't use any forms in the my addin. Any hints on how to invoke an event on a main thread without having access to Control.Invoke? |
#5
|
|||
|
|||
![]()
That's exactly what I have, but when the event is fired, and I breakpoint the
event code, visual studio shows it's still running in the worker thread. Is VS being a little misleading in it's thread monitoring? One thing I want to be clear about in your example: the OnHelloUserDone method is actually called on the worker thread, correct? "Ken Slovak - [MVP - Outlook]" wrote: Something like this for the delegate events: // In the class for the background worker: internal delegate void HelloUserDoneEventHandler(object sender, EventArgs e); internal event HelloUserDoneEventHandler HelloUserDone; // make a call in the code that handles worker done to OnHelloUserDone() protected virtual void OnHelloUserDone(EventArgs e) { HelloUserDoneEventHandler handler = HelloUserDone; if (handler != null) { // Invokes the delegate. handler(this, e); } } // in the code in the main class or wherever private void HelloUser(object sender, EventArgs e) { if (e.Result != null) { // event fired, work done } } Of course in the main code you'd need to instantiate the HelloUser event handler, something like this, where myWorker is the class that has the background worker: _worker.HelloUserDone += new myWorker.HelloUserDoneEventHandler(HelloUser); -- Ken Slovak [MVP - Outlook] http://www.slovaktech.com Author: Professional Programming Outlook 2007. Reminder Manager, Extended Reminders, Attachment Options. http://www.slovaktech.com/products.htm "Dorian" wrote in message ... Using a struct for the MailItem information makes sense, and if I am able to, using a delegate event handler to return to the main thread makes sense. In my previous experiences I've used the Invoke method of the control that the main thread is being run on. Unfortunately I don't use any forms in the my addin. Any hints on how to invoke an event on a main thread without having access to Control.Invoke? |
#6
|
|||
|
|||
![]()
I noticed that the only difference was that you mentioned the worker thread
should maintain a separate class. I think that should make the difference. I'll make some changes and check in again. Thanks for the help so far, it's much appreciated. |
#7
|
|||
|
|||
![]()
Putting it in a different class doesn't fix the problem. The event gets
triggered on the worker thread. "Dorian" wrote: That's exactly what I have, but when the event is fired, and I breakpoint the event code, visual studio shows it's still running in the worker thread. Is VS being a little misleading in it's thread monitoring? One thing I want to be clear about in your example: the OnHelloUserDone method is actually called on the worker thread, correct? "Ken Slovak - [MVP - Outlook]" wrote: Something like this for the delegate events: // In the class for the background worker: internal delegate void HelloUserDoneEventHandler(object sender, EventArgs e); internal event HelloUserDoneEventHandler HelloUserDone; // make a call in the code that handles worker done to OnHelloUserDone() protected virtual void OnHelloUserDone(EventArgs e) { HelloUserDoneEventHandler handler = HelloUserDone; if (handler != null) { // Invokes the delegate. handler(this, e); } } // in the code in the main class or wherever private void HelloUser(object sender, EventArgs e) { if (e.Result != null) { // event fired, work done } } Of course in the main code you'd need to instantiate the HelloUser event handler, something like this, where myWorker is the class that has the background worker: _worker.HelloUserDone += new myWorker.HelloUserDoneEventHandler(HelloUser); -- Ken Slovak [MVP - Outlook] http://www.slovaktech.com Author: Professional Programming Outlook 2007. Reminder Manager, Extended Reminders, Attachment Options. http://www.slovaktech.com/products.htm "Dorian" wrote in message ... Using a struct for the MailItem information makes sense, and if I am able to, using a delegate event handler to return to the main thread makes sense. In my previous experiences I've used the Invoke method of the control that the main thread is being run on. Unfortunately I don't use any forms in the my addin. Any hints on how to invoke an event on a main thread without having access to Control.Invoke? |
#8
|
|||
|
|||
![]()
OnHelloUserDone() is a virtual method in the worker class. It calls to any
event handlers that match the signature of the HelloUserDoneEventHandler delegate. Those handlers are in other classes and have registered to handle the event. If they do not match the signature or haven't registered for the event they won't get called. -- Ken Slovak [MVP - Outlook] http://www.slovaktech.com Author: Professional Programming Outlook 2007. Reminder Manager, Extended Reminders, Attachment Options. http://www.slovaktech.com/products.htm "Dorian" wrote in message ... That's exactly what I have, but when the event is fired, and I breakpoint the event code, visual studio shows it's still running in the worker thread. Is VS being a little misleading in it's thread monitoring? One thing I want to be clear about in your example: the OnHelloUserDone method is actually called on the worker thread, correct? |
#9
|
|||
|
|||
![]()
On 5 Sep, 18:19, Dorian wrote:
Is there any way to trigger an event on the main thread once the worker thread has finished running? I am used to doing this with forms, and having a worker thread invoke a delegate on the main form. Since we're not working with forms, or even controls for that matter, how would I go about doing this? Create a simple Windows Forms control to do the thread switching for you. It does not need be bound to a form. In main thread: Control threadMarshaler; // member field //... threadMarshaler = new Control(); IntPtr dontcare = threadMarshaler.Handle; // Force creation of necessary message pump In worker thread: threadMarshaler.Invoke(...); |
Thread Tools | Search this Thread |
Display Modes | |
|
|