![]() |
|
Multithreading with C#
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? |
Multithreading with C#
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 ... 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? |
Multithreading with C#
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 ... 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? |
Multithreading with C#
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? |
Multithreading with C#
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? |
Multithreading with C#
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. |
Multithreading with C#
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? |
Multithreading with C#
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? |
Multithreading with C#
The work complete event fires in the worker thread. Then you call the
virtual event handler in the worker thread. That calls the delegates which are located in other classes. The delegates must be registered to handle the event. -- 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 ... Putting it in a different class doesn't fix the problem. The event gets triggered on the worker thread. |
Multithreading with C#
Ok, so here's what I do:
// Main Class public partial class ThisAddIn { private void Explorer_SelectionChange() { ReceivedMailHandler rmh = new ReceivedMailHandler(); // Do some stuff (Add data to the object) rmh.SupportExceptionThrown += new ReceivedMailHandler.SupportExceptionDelegate(rmh_S upportExceptionThrown); rmh.SupportIgnoreChanged += new ReceivedMailHandler.SupportIgnoreDelegate(rmh_Supp ortIgnoreChanged); Thread th = new Thread(rmh.ParseAndInsertReceivedMail); th.IsBackground = true; th.Start(); } void rmh_SupportIgnoreChanged(bool IsVisible) { btnExpIgnore.Visible = IsVisible; //Breakpoint here } void rmh_SupportExceptionThrown(Exception ex) { string blah = "asd"; //Breakpoint here } } // Worker Class class ReceivedMailHandler { public delegate void SupportExceptionDelegate(Exception ex); public delegate void SupportIgnoreDelegate(bool IsVisible); public void ParseAndInsertReceivedMail() { // Do work (no OOM objects) RaiseIgnoreChange(true); RaiseException(new Exception("blah")); } private void RaiseException(Exception ex) { SupportExceptionDelegate sed = SupportExceptionThrown; if (sed != null) sed(ex); } private void RaiseIgnoreChange(bool isVisible) { SupportIgnoreDelegate sid = SupportIgnoreChanged; if (sid != null) sid(isVisible); } } When it hits the breakpoints on rmh_SupportIgnoreChanged and rmh_SupportExceptionThrown, both are still in the worker thread. "Ken Slovak - [MVP - Outlook]" wrote: 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? |
All times are GMT +1. The time now is 12:26 PM. |
|
Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Search Engine Friendly URLs by vBSEO 2.4.0
Copyright ©2004-2006 OutlookBanter.com