Threading, Outlook 2007

A

Aidal

Hi everyone.

I'm working on an add-in for Outlook 2007 (VS2005 with VSTO 2005 SE) in
which threading is required due to some actions taking a period of time to
finish and I don't want to freeze up my UI.

I have encountered a problem though, that I haven't seen before.

I've tried using the BackgroundWorker ("bgw" from now on) and also the
ExtendedBackgroundWorker found on Roy Osherove's Blog
(http://weblogs.asp.net/rosherove/pages/BackgroundWorkerEx.aspx) (nice work
by the way with the new cancel instantly feature) but the result is the same.

I can start to do work with the bgw just fine but once the bgw finishes it's
work and I wish to update my UI in some way, I get the "cross-thread action"
error.

This happens almost regardless of what I'm doing with the UI, even if I just
want to change .Enabled from false to true on a button.

There is one thing that I've seen not being affected though and that's a
PictureBox I'm using.

At first I tried to work with a progress bar, but the updating of it didn't
go down well, so I used one of these animated gifs that just shows that
"somthing is going on (well not really but it looks like it knows somthing).

So giving the PictureBox.Image the gif just before calling
bgw.RunWorkerAsync() and then setting the PictureBox.Image = null once the
bgw finished works (aka I can change this UI component without any errors)
but everything else on the UI I cannot touch once the bgw finishes...

Why is this and is there a solution to this problem out there?
(please don't tell me it's another of these sweet limitations)

Thanks,
/Aidal
 
A

Aidal

Oh by the way, I don't know if this changes things at all but I forgot to
mention that what I'm doing is not in an Outlook form but in a User Control
which is added to Outlook as a Microsoft.Office.Tools.CustomTaskPane.

/Aidal
 
A

Aidal

I've switched away from the User Control and I'm now using a normal Windows
Form instead to try and anrrow down the possible error sources.

The issue is still the same though :(

Where are some an example of what I'm trying to do:
------------------------------------------------------------
// InitializeExBgw() is called in the form constructor.

private void InitializeExBgw()
{
this.ExBgw = new ExtendedBackgroundWorker();

this.ExBgw.DoWork += new DoWorkEventHandler(ExBgw_DoWork);
this.ExBgw.RunWorkerCompleted += new
RunWorkerCompletedEventHandler(ExBgw_RunWorkerCompleted);
}

private void ExBgw_DoWork(object sender, DoWorkEventArgs e)
{
ExtendedBackgroundWorker worker = sender as
ExtendedBackgroundWorker;

SQLServerLocator locator = new SQLServerLocator(); // My own
class. Scans for SQL servers on the network.

string[] servers = locator.GetServers();

e.Result = (string[])alTemp.ToArray(typeof(string));
}

private void ExBgw_RunWorkerCompleted(object sender,
RunWorkerCompletedEventArgs e)
{
string[] servers = new string[] { "" };

if (e.Error != null)
{
MessageBox.Show(this.Init.GetLanguageMessageError(2, "\n\n",
e.Error.Message), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
else if (e.Cancelled)
{
}
else
{
if (e.Result != null)
{
servers = (string[])e.Result;

// this part will produce the cross-thread error
foreach(string s in servers)
{
this.ComboBox1.Items.Add(s);
}
}
}

// this however, does not produce the cross-thread error
this.PictureBox1.Image = null;
}

private void btn_Search_SQLServers_Click(object sender, EventArgs e)
{
this.PictureBox1.Image = "my_progress_gif_file.gif";

this.ExBgw.RunWorkerAsync(null); // used to send an object with
it, but it's not used in this example, hence "null".
}
------------------------------------------------------

Why can I load an image into a PictureBox but not populate a ComboBox or set
the Text property on a Label for that matter in "ExBgw_RunWorkerCompleted" ???

This doesn't make sense to me...

/Aidal
 
A

Aidal

Seriously, nobody knows how to do this in Outlook or a simple windows
form in an add-in?
I've switched away from the User Control and I'm now using a normal Windows
Form instead to try and anrrow down the possible error sources.

The issue is still the same though :(

Where are some an example of what I'm trying to do:
------------------------------------------------------------
// InitializeExBgw() is called in the form constructor.

private void InitializeExBgw()
{
this.ExBgw = new ExtendedBackgroundWorker();

this.ExBgw.DoWork += new DoWorkEventHandler(ExBgw_DoWork);
this.ExBgw.RunWorkerCompleted += new
RunWorkerCompletedEventHandler(ExBgw_RunWorkerCompleted);
}

private void ExBgw_DoWork(object sender, DoWorkEventArgs e)
{
ExtendedBackgroundWorker worker = sender as
ExtendedBackgroundWorker;

SQLServerLocator locator = new SQLServerLocator(); // My own
class. Scans for SQL servers on the network.

string[] servers = locator.GetServers();

e.Result = (string[])alTemp.ToArray(typeof(string));
}

private void ExBgw_RunWorkerCompleted(object sender,
RunWorkerCompletedEventArgs e)
{
string[] servers = new string[] { "" };

if (e.Error != null)
{
MessageBox.Show(this.Init.GetLanguageMessageError(2, "\n\n",
e.Error.Message), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
else if (e.Cancelled)
{
}
else
{
if (e.Result != null)
{
servers = (string[])e.Result;

// this part will produce the cross-thread error
foreach(string s in servers)
{
this.ComboBox1.Items.Add(s);
}
}
}

// this however, does not produce the cross-thread error
this.PictureBox1.Image = null;
}

private void btn_Search_SQLServers_Click(object sender, EventArgs e)
{
this.PictureBox1.Image = "my_progress_gif_file.gif";

this.ExBgw.RunWorkerAsync(null); // used to send an object with
it, but it's not used in this example, hence "null".
}
------------------------------------------------------

Why can I load an image into a PictureBox but not populate a ComboBox or set
the Text property on a Label for that matter in "ExBgw_RunWorkerCompleted" ???

This doesn't make sense to me...

/Aidal

Aidal said:
Oh by the way, I don't know if this changes things at all but I forgot to
mention that what I'm doing is not in an Outlook form but in a User Control
which is added to Outlook as a Microsoft.Office.Tools.CustomTaskPane.

/Aidal
 
K

Ken Slovak - [MVP - Outlook]

I don't think there's a lot of expertise here in working with background
threads.

I'd suggest taking a look at Outlook MVP Jay Harlow's Web site and sample
for using a background worker thread at
http://www.tsbradley.net/Samples/VSTO/Xml.Export.Sample.aspx and reviewing
his work with background worker threads and see if that gives you any clues.

His example is written using VB.NET and VSTO 2 so you will need an
installation of Outlook 2003 and a compatible setup of VS to open the
project or you can just unpack the zip and port the code modules into a
compatible setup you have.




Aidal said:
Seriously, nobody knows how to do this in Outlook or a simple windows form
in an add-in?
I've switched away from the User Control and I'm now using a normal
Windows Form instead to try and anrrow down the possible error sources.

The issue is still the same though :(

Where are some an example of what I'm trying to do:
------------------------------------------------------------
// InitializeExBgw() is called in the form constructor.

private void InitializeExBgw()
{
this.ExBgw = new ExtendedBackgroundWorker();

this.ExBgw.DoWork += new DoWorkEventHandler(ExBgw_DoWork);
this.ExBgw.RunWorkerCompleted += new
RunWorkerCompletedEventHandler(ExBgw_RunWorkerCompleted);
}

private void ExBgw_DoWork(object sender, DoWorkEventArgs e)
{
ExtendedBackgroundWorker worker = sender as
ExtendedBackgroundWorker;

SQLServerLocator locator = new SQLServerLocator(); // My own
class. Scans for SQL servers on the network.

string[] servers = locator.GetServers();

e.Result = (string[])alTemp.ToArray(typeof(string));
}

private void ExBgw_RunWorkerCompleted(object sender,
RunWorkerCompletedEventArgs e)
{
string[] servers = new string[] { "" };
if (e.Error != null)
{
MessageBox.Show(this.Init.GetLanguageMessageError(2,
"\n\n", e.Error.Message), "Error", MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
else if (e.Cancelled)
{
}
else
{
if (e.Result != null)
{
servers = (string[])e.Result;

// this part will produce the cross-thread error
foreach(string s in servers)
{
this.ComboBox1.Items.Add(s);
} }
}

// this however, does not produce the cross-thread error
this.PictureBox1.Image = null;
}

private void btn_Search_SQLServers_Click(object sender, EventArgs e)
{
this.PictureBox1.Image = "my_progress_gif_file.gif";

this.ExBgw.RunWorkerAsync(null); // used to send an object
with it, but it's not used in this example, hence "null".
}
------------------------------------------------------

Why can I load an image into a PictureBox but not populate a ComboBox or
set the Text property on a Label for that matter in
"ExBgw_RunWorkerCompleted" ???

This doesn't make sense to me...

/Aidal

Aidal said:
Oh by the way, I don't know if this changes things at all but I forgot
to mention that what I'm doing is not in an Outlook form but in a User
Control which is added to Outlook as a
Microsoft.Office.Tools.CustomTaskPane.

/Aidal

:

Hi everyone.

I'm working on an add-in for Outlook 2007 (VS2005 with VSTO 2005 SE) in
which threading is required due to some actions taking a period of time
to finish and I don't want to freeze up my UI.

I have encountered a problem though, that I haven't seen before.

I've tried using the BackgroundWorker ("bgw" from now on) and also the
ExtendedBackgroundWorker found on Roy Osherove's Blog
(http://weblogs.asp.net/rosherove/pages/BackgroundWorkerEx.aspx) (nice
work by the way with the new cancel instantly feature) but the result
is the same.

I can start to do work with the bgw just fine but once the bgw finishes
it's work and I wish to update my UI in some way, I get the
"cross-thread action" error.

This happens almost regardless of what I'm doing with the UI, even if I
just want to change .Enabled from false to true on a button.

There is one thing that I've seen not being affected though and that's
a PictureBox I'm using.

At first I tried to work with a progress bar, but the updating of it
didn't go down well, so I used one of these animated gifs that just
shows that "somthing is going on (well not really but it looks like it
knows somthing).

So giving the PictureBox.Image the gif just before calling
bgw.RunWorkerAsync() and then setting the PictureBox.Image = null once
the bgw finished works (aka I can change this UI component without any
errors) but everything else on the UI I cannot touch once the bgw
finishes...
Why is this and is there a solution to this problem out there?
(please don't tell me it's another of these sweet limitations)

Thanks,
/Aidal
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top