RDOMail object is not working in different thread.

  • Thread starter Thread starter Sandeep K
  • Start date Start date
S

Sandeep K

Hi,
I am using RDOMail object to retrieve email data and setting user
properties. RDOMail object works fine in the main thread, 'ThisAddin thread',
(I am creating VSTO Add-in) but when I use same RDOObject in the worker
thread all function calls on the RDOMail object in debugger evaluates to
error "Function evaluation disabled because a previous function evaluation
timed out. You must continue execution to reenable function evaluation.".

Any clue how can i use RDOMail object in worker thread which is different
thread than ThisAddin thread.
 
Sure. Set up the code to run with server side MAPI on a machine that never
has had Outlook installed.

What you want won't work. It will hang or crash Outlook and/or your addin
code. Think of a different method such as getting the information in the
foreground thread and then passing strings or whatever to the background
thread. Otherwise you're just causing yourself plus any other code running
on that machine nothing but headaches.
 
Hi Ken,
The problem here is getting the information back from the background worker
thread. My scenario is like this:
I do some processing based on the content of email and then based on the
result I update the mail object properties. As I am using a background
workder thread for processing email content, I can now pass the email content
directly to the background worker. Now as background worker thread can not
access mail object, I believe I need the processing results to be passed back
to Main thread. Is there a way to pass the result back to main thread so that
It can set properties of the emails.
 
There are a few ways to pass data back and forth, depending on how you want
to implement something like that.

The simplest way is a set of public or internal data that both threads have
access to.

You can also get the thread context of the main thread and store that in an
accessible place, then a call from the background thread can pass data to a
procedure and synch that using a SendOrPost() callback.

I often use that methodology for WordMail related things for Outlook 2003,
where Word is running on a different thread than the Outlook process.
 
All threads that use Extended MAPI must call MAPIInitialize. Outlook calls
it on its main thread, but if you create your own secondary thread, that is
your responsibility.
All creatable Redemption objects (including RDOSession) do that. Try to
create an instance of the RDOSession object on the secondary thread, sets
its MAPIOBJECT property to Application.Session.MAPIOBJECT from Outlook to
make sure the two share the same MAPI sessio, then retrieve RDOMail.
--
Dmitry Streblechenko (MVP)
http://www.dimastr.com/
OutlookSpy - Outlook, CDO
and MAPI Developer Tool
-
 
Thanks Dmitry sir,
I respect you a lot. Redemption provides a lot of functionality and we can't
complete our work without it. But we are very new for outlook add-in
development. I take a list rdomails in main thread and then process this list
on secondary thread for submission task to some server. Do you want me to
just send list of EntryIDs of mails and then create RDOMail object here in
secondary thread.

Lets say I do as I said above. How should i release RDOMails created in main
thread? (RDOMails are required in main thread as well since we set some user
property there)

Please advise.
 
I tried following two code segment in secondary thread but niether is
working. RDOMail evaluates to same error.

RDOSession rsession = new RDOSessionClass();
Outlook.Application app = new Outlook.ApplicationClass();
rsession.MAPIOBJECT = app.Session.MAPIOBJECT;
ArrayList rmails = new ArrayList();
foreach (string entryId in maillist)
{
RDOMail rmail = rsession.GetMessageFromID(entryId,
System.Reflection.Missing.Value, System.Reflection.Missing.Value);

rmails.Add(rmail);
}

or
RDOSession rsession = new RDOSessionClass();
rsession.MAPIOBJECT = Globals.AddinMain.Application.Session.MAPIOBJECT;
foreach (string entryId in maillist)
{
RDOMail rmail = rsession.GetMessageFromID(entryId,
System.Reflection.Missing.Value, System.Reflection.Missing.Value);

rmails.Add(rmail);
}

please advise.
 
Yes, save the entry ids, then reopen the messages on the second thread using
RDOSession.GetMessageFormID

--
Dmitry Streblechenko (MVP)
http://www.dimastr.com/
OutlookSpy - Outlook, CDO
and MAPI Developer Tool
-
 
In your second example, can you access any properties in teh code rather
than in the debugger?

string Subject = rmail.Subject;

Can you see the value of the Subject variable?

--
Dmitry Streblechenko (MVP)
http://www.dimastr.com/
OutlookSpy - Outlook, CDO
and MAPI Developer Tool
-
 
After reading some blogs on net. I am in agreement with ken not to do
anything related to mails object in other than main thread hence i have
created one Backgroundworker component in which i do long task in dowork()
event and I update RDOMails object in ProgressChanged and RunWorkerCompleted
event. Dowork eventhandler is secondary thread and code in ProgressChanged
and RunWorkerCompleted event handler executes in main thread. Now i do not
see any debugger errors. Though I am setting them in Progresschanged event
and saving email on RunWorkerCompleted event, I can not see user porperties
value in explorer view. Any clue?

Code example:
//Initialize the backgroundworker and RDOSession object. This code executes
in mainthread.
static MailSubmission()
{
backgroundWorker1 = new System.ComponentModel.BackgroundWorker();
InitializeBackgroundWorker();
rsession = new RDOSessionClass();
rsession.MAPIOBJECT =
Globals.AddinMain.Application.Session.MAPIOBJECT;
}
//Code executes in main thread
private static void backgroundWorker1_RunWorkerCompleted(
object sender, RunWorkerCompletedEventArgs e)
{

string entryId = (string)e.Result;
RDOMail rmail = rsession.GetMessageFromID(entryId,
System.Reflection.Missing.Value, System.Reflection.Missing.Value);
rmail.Save();
}

private static void backgroundWorker1_ProgressChanged(object sender,
ProgressChangedEventArgs e)
{
string entryId = (string)e.UserState;
RDOMail rmail = rsession.GetMessageFromID(entryId,
System.Reflection.Missing.Value, System.Reflection.Missing.Value);
RDOUserProperty prop = rmail.UserProperties.Find(someproperty, true);
prop.value = "something";
}
//Code executes in secondary thread
private static void backgroundWorker1_DoWork(object sender,
DoWorkEventArgs e)
{
string emailEntryId= (string)e.Argument;
// Get the BackgroundWorker that raised this event.
BackgroundWorker worker = sender as BackgroundWorker;
Thread.Sleep(1000);
worker.ReportProgress(33, userstate);
Thread.Sleep(1000);
worker.ReportProgress(66, userstate);
Thread.Sleep(1000);
e.Result = emailEntryId;
}
 
Are you saving the RDOMail item? Do you see the value in the Explorer if you
change folders and back again or stop and restart Outlook?

You might have to tell Outlook something has changed since it won't reflect
changes at the MAPI level otherwise. Usually we use something like this to
tell Outlook something has changed: item.Subject = item.Subject, then we
save the item.
 
And also why are you saving teh mesasge immediately after callign
GetMessageFromID? You need to save it after after you make changes.

--
Dmitry Streblechenko (MVP)
http://www.dimastr.com/
OutlookSpy - Outlook, CDO
and MAPI Developer Tool
-
 
Thanks a lot things are now working for me.

Ken Slovak - said:
Are you saving the RDOMail item? Do you see the value in the Explorer if you
change folders and back again or stop and restart Outlook?

You might have to tell Outlook something has changed since it won't reflect
changes at the MAPI level otherwise. Usually we use something like this to
tell Outlook something has changed: item.Subject = item.Subject, then we
save the item.
 
Thanks a lot things are now working for me.

Dmitry Streblechenko said:
And also why are you saving teh mesasge immediately after callign
GetMessageFromID? You need to save it after after you make changes.

--
Dmitry Streblechenko (MVP)
http://www.dimastr.com/
OutlookSpy - Outlook, CDO
and MAPI Developer Tool
-
 
Back
Top