Threading guru required!

M

Mike P

I am trying to write my first program using threading..basically I am
moving messages from an Outlook inbox and want to show the user where
the process is up to without having to wait until it has finished. I am
trying to follow this example :
http://www.codeproject.com/cs/miscctrl/progressdialog.asp

But although the messages still get moved, the progress window never
does anything. Here is my code in full, if anybody who knows anything
about threading could help me, it would be much appreciated!

Form1.cs :

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Outlook;

namespace WindowsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose(disposing);
}

private void btnGo_Click(object sender, EventArgs e)
{
ProgressWindow progress = new ProgressWindow();
progress.Text = "Work";
System.Threading.ThreadPool.QueueUserWorkItem(new
System.Threading.WaitCallback(DoSomeWork), progress);
progress.ShowDialog();
}

private void DoSomeWork(object status)
{
IProgressCallback callback = status as IProgressCallback;

try
{
Outlook.Application oApp = new
Outlook.ApplicationClass();

//Get MAPI namespace
Outlook.NameSpace oNS = oApp.GetNamespace("mapi");

string strUserName =
System.Environment.UserName.ToString();

try
{
oNS.Logon(strUserName,
System.Reflection.Missing.Value, false, true);
}
catch
{
throw new LogonException();
}

//Get Messages collection of Inbox
Outlook.MAPIFolder oInbox =
oNS.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox);

try
{
Outlook.MAPIFolder destfolderTest =
oInbox.Folders.Item("Archive");
}
catch
{
throw new MissingFolderException();
}

Outlook.MAPIFolder destfolder =
oInbox.Folders.Item("Archive");

Outlook.Items oItems = oInbox.Items;

int intTotalNumberOfItemsInInbox = oItems.Count;

if (intTotalNumberOfItemsInInbox == 0)
throw new NoMessagesException();

//Get unread e-mail messages
//oItems = oItems.Restrict("[Unread] = true");
//int intTotalUnread = oItems.Count;

//DataTable dt = new DataTable();
//DataRow dr;

//dt.Columns.Add("ReceivedByName");
//dt.Columns.Add("SenderName");
//dt.Columns.Add("ReceivedTime");
//dt.Columns.Add("Subject");
//dt.Columns.Add("Body");

//Outlook.MailItem oMsg;
//int i;

//database connection
SqlConnection objConn = new SqlConnection();
objConn.ConnectionString = "server=e2bvsql4\\inst1; user
id=datawriter; password=rover9; database=SurveyResults";

try
{
objConn.Open();
}
catch
{
throw new DatabaseException();
}

//string strInsertQuery = "";

callback.Begin(0, intTotalNumberOfItemsInInbox);

for (int i = 0; i < oItems.Count; i++)
{
callback.SetText(String.Format("Performing op: {0}",
i));
callback.StepTo(i);

if (callback.IsAborting)
{
return;
}

oItems = oInbox.Items;
MoveMail(oItems, destfolder, objConn);

if (oItems.Count == 1)
{
i = -1;
}
else
{
i = 0;
}
}

objConn.Close();

//Loop through each unread message
//for (i = 1; i < intTotalNumberOfItemsInInbox + 1; i++)
//{
// //check if appointment or meeting request
// if (oItems.Item(i) is Outlook.MailItem)
// {
// oMsg = (Outlook.MailItem)oItems.Item(i);

//dr = dt.NewRow();
//dr["ReceivedByName"] = oMsg.ReceivedByName.ToString();
//dr["SenderName"] = oMsg.SenderName.ToString();
//dr["ReceivedTime"] = oMsg.ReceivedTime.ToString();
//dr["Subject"] = oMsg.Subject.ToString();
//dr["Body"] = oMsg.Body.ToString();
//dt.Rows.Add(dr);

////subject
//if ((oMsg.Subject == null) || (oMsg.Subject == ""))
//{
// oMsg.Subject = "blank";
//}
//else
//{
// //escape quotes in subject
// oMsg.Subject = oMsg.Subject.Replace("'", "''");
//}

//if (oMsg.ReceivedByName == null)
//{
// if (oMsg.SenderName.IndexOf("'") != -1)
// {
// string strSenderName =
oMsg.SenderName.Replace("'", "''");

// strInsertQuery = "INSERT INTO SeedingResults
(SenderName, ReceivedTime, Subject) VALUES ('" + strSenderName + "','" +
oMsg.ReceivedTime.ToString() + "','" + oMsg.Subject.ToString() + "')";
// }
// else
// {
// strInsertQuery = "INSERT INTO SeedingResults
(SenderName, ReceivedTime, Subject) VALUES ('" +
oMsg.SenderName.ToString() + "','" + oMsg.ReceivedTime.ToString() +
"','" + oMsg.Subject.ToString() + "')";
// }
//}
//else
//{
// if (oMsg.SenderName.IndexOf("'") != -1)
// {
// string strSenderName2 =
oMsg.SenderName.Replace("'", "''");

// strInsertQuery = "INSERT INTO SeedingResults
(ReceivedByName, SenderName, ReceivedTime, Subject) VALUES ('" +
oMsg.ReceivedByName.ToString() + "','" + strSenderName2 + "','" +
oMsg.ReceivedTime.ToString() + "','" + oMsg.Subject.ToString() + "')";
// }
// else
// {
// strInsertQuery = "INSERT INTO SeedingResults
(ReceivedByName, SenderName, ReceivedTime, Subject) VALUES ('" +
oMsg.ReceivedByName.ToString() + "','" + oMsg.SenderName.ToString() +
"','" + oMsg.ReceivedTime.ToString() + "','" + oMsg.Subject.ToString() +
"')";
// }
//}

////write to database
//SqlCommand objInsertCommand = new
SqlCommand(strInsertQuery, objConn);

//try
//{
//objConn.Open();

//objInsertCommand.ExecuteNonQuery();

//objConn.Close();
//}
//catch
//{
// throw new DatabaseException();
//}

//move record to archive folder
//oMsg.Move(destfolder);
// }
//}

//dataGridView1.DataSource = dt;
//GridView1.DataSource = dt;
//GridView1.DataBind();

//Log off
oNS.Logoff();

//Clean up
oApp = null;
oNS = null;
oItems = null;
//oMsg = null;

//inform user of success
lblStatus.ForeColor = System.Drawing.Color.Blue;
lblStatus.Text = "**Inbox messages successfully
transferred**";
}
catch (LogonException le)
{
lblStatus.ForeColor = System.Drawing.Color.Red;
lblStatus.Text = "**Outlook Logon Error**";
}
catch (MissingFolderException mfe)
{
lblStatus.ForeColor = System.Drawing.Color.Red;
lblStatus.Text = "**Please create Archive folder within
local Inbox folder**";
}
catch (NoMessagesException nme)
{
lblStatus.ForeColor = System.Drawing.Color.Red;
lblStatus.Text = "**There are no messages in the local
Inbox to be transferred**";
}
catch (DatabaseException se)
{
lblStatus.ForeColor = System.Drawing.Color.Red;
lblStatus.Text = "**Database Error**";
}
catch( System.Threading.ThreadAbortException )
{
// We want to exit gracefully here (if we're lucky)
}
catch( System.Threading.ThreadInterruptedException )
{
// And here, if we can
}
catch
{
lblStatus.ForeColor = System.Drawing.Color.Red;
lblStatus.Text = "**General Exception**";
}
finally
{
if (callback != null)
{
callback.End();
}
}
}

private void MoveMail(Outlook.Items col, Outlook.MAPIFolder
destfolder, SqlConnection objConn)
{
string strInsertQuery = "";

for (int i = 1; i < col.Count + 1; i++)
{
if (col.Item(i) is Outlook.MailItem)
{
Outlook.MailItem oMsg =
(Outlook.MailItem)col.Item(i);

//subject
if ((oMsg.Subject == null) || (oMsg.Subject == ""))
{
oMsg.Subject = "blank";
}
else
{
//escape quotes in subject
oMsg.Subject = oMsg.Subject.Replace("'", "''");
}

if (oMsg.ReceivedByName == null)
{
if (oMsg.SenderName.IndexOf("'") != -1)
{
string strSenderName =
oMsg.SenderName.Replace("'", "''");

strInsertQuery = "INSERT INTO SeedingResults
(SenderName, ReceivedTime, Subject) VALUES ('" + strSenderName + "','" +
oMsg.ReceivedTime.ToString() + "','" + oMsg.Subject.ToString() + "')";
}
else
{
strInsertQuery = "INSERT INTO SeedingResults
(SenderName, ReceivedTime, Subject) VALUES ('" +
oMsg.SenderName.ToString() + "','" + oMsg.ReceivedTime.ToString() +
"','" + oMsg.Subject.ToString() + "')";
}
}
else
{
if (oMsg.SenderName.IndexOf("'") != -1)
{
string strSenderName2 =
oMsg.SenderName.Replace("'", "''");

strInsertQuery = "INSERT INTO SeedingResults
(ReceivedByName, SenderName, ReceivedTime, Subject) VALUES ('" +
oMsg.ReceivedByName.ToString() + "','" + strSenderName2 + "','" +
oMsg.ReceivedTime.ToString() + "','" + oMsg.Subject.ToString() + "')";
}
else
{
strInsertQuery = "INSERT INTO SeedingResults
(ReceivedByName, SenderName, ReceivedTime, Subject) VALUES ('" +
oMsg.ReceivedByName.ToString() + "','" + oMsg.SenderName.ToString() +
"','" + oMsg.ReceivedTime.ToString() + "','" + oMsg.Subject.ToString() +
"')";
}
}

//write to database
SqlCommand objInsertCommand = new
SqlCommand(strInsertQuery, objConn);

try
{
objInsertCommand.ExecuteNonQuery();
}
catch
{
throw new DatabaseException();
}

oMsg.Move(destfolder);
}
}
}
}
}

IProcessCallback.cs :

using System;

namespace WindowsApplication1
{
/// <summary>
/// This defines an interface which can be implemented by UI
elements
/// which indicate the progress of a long operation.
/// (See ProgressWindow for a typical implementation)
/// </summary>
public interface IProgressCallback
{
/// <summary>
/// Call this method from the worker thread to initialize
/// the progress callback.
/// </summary>
/// <param name="minimum">The minimum value in the progress
range (e.g. 0)</param>
/// <param name="maximum">The maximum value in the progress
range (e.g. 100)</param>
void Begin(int minimum, int maximum);

/// <summary>
/// Call this method from the worker thread to initialize
/// the progress callback, without setting the range
/// </summary>
void Begin();

/// <summary>
/// Call this method from the worker thread to reset the range
in the progress callback
/// </summary>
/// <param name="minimum">The minimum value in the progress
range (e.g. 0)</param>
/// <param name="maximum">The maximum value in the progress
range (e.g. 100)</param>
/// <remarks>You must have called one of the Begin() methods
prior to this call.</remarks>
void SetRange(int minimum, int maximum);

/// <summary>
/// Call this method from the worker thread to update the
progress text.
/// </summary>
/// <param name="text">The progress text to display</param>
/// <remarks>You must have called one of the Begin() methods
prior to this call.</remarks>
void SetText(String text);

/// <summary>
/// Call this method from the worker thread to increase the
progress counter by a specified value.
/// </summary>
/// <param name="val">The amount by which to increment the
progress indicator</param>
/// <remarks>You must have called one of the Begin() methods
prior to this call.</remarks>
void StepTo(int val);

/// <summary>
/// Call this method from the worker thread to step the progress
meter to a particular value.
/// </summary>
/// <param name="val">The value to which to step the
meter</param>
/// <remarks>You must have called one of the Begin() methods
prior to this call.</remarks>
void Increment(int val);

/// <summary>
/// If this property is true, then you should abort work
/// </summary>
/// <remarks>You must have called one of the Begin() methods
prior to this call.</remarks>
bool IsAborting
{
get;
}

/// <summary>
/// Call this method from the worker thread to finalize the
progress meter
/// </summary>
/// <remarks>You must have called one of the Begin() methods
prior to this call.</remarks>
void End();
}
}

ProgressWindow.cs :

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;

namespace MWA.Progress
{
/// <summary>
/// Summary description for ProgressWindow.
/// </summary>
public class ProgressWindow : System.Windows.Forms.Form,
IProgressCallback
{
private System.Windows.Forms.Button cancelButton;
private System.Windows.Forms.Label label;
private System.Windows.Forms.ProgressBar progressBar;

/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;

public delegate void SetTextInvoker(String text);
public delegate void IncrementInvoker( int val );
public delegate void StepToInvoker( int val );
public delegate void RangeInvoker( int minimum, int maximum );

private String titleRoot = "";
private System.Threading.ManualResetEvent initEvent = new
System.Threading.ManualResetEvent(false);
private System.Threading.ManualResetEvent abortEvent = new
System.Threading.ManualResetEvent(false);
private bool requiresClose = true;

public ProgressWindow()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
}

#region Implementation of IProgressCallback
/// <summary>
/// Call this method from the worker thread to initialize
/// the progress meter.
/// </summary>
/// <param name="minimum">The minimum value in the progress range
(e.g. 0)</param>
/// <param name="maximum">The maximum value in the progress range
(e.g. 100)</param>
public void Begin( int minimum, int maximum )
{
initEvent.WaitOne();
Invoke( new RangeInvoker( DoBegin ), new object[] { minimum, maximum
} );
}

/// <summary>
/// Call this method from the worker thread to initialize
/// the progress callback, without setting the range
/// </summary>
public void Begin()
{
initEvent.WaitOne();
Invoke( new MethodInvoker( DoBegin ) );
}

/// <summary>
/// Call this method from the worker thread to reset the range in the
progress callback
/// </summary>
/// <param name="minimum">The minimum value in the progress range
(e.g. 0)</param>
/// <param name="maximum">The maximum value in the progress range
(e.g. 100)</param>
/// <remarks>You must have called one of the Begin() methods prior to
this call.</remarks>
public void SetRange( int minimum, int maximum )
{
initEvent.WaitOne();
Invoke( new RangeInvoker( DoSetRange ), new object[] { minimum,
maximum } );
}

/// <summary>
/// Call this method from the worker thread to update the progress
text.
/// </summary>
/// <param name="text">The progress text to display</param>
public void SetText( String text )
{
Invoke( new SetTextInvoker(DoSetText), new object[] { text } );
}

/// <summary>
/// Call this method from the worker thread to increase the progress
counter by a specified value.
/// </summary>
/// <param name="val">The amount by which to increment the progress
indicator</param>
public void Increment( int val )
{
Invoke( new IncrementInvoker( DoIncrement ), new object[] { val } );
}

/// <summary>
/// Call this method from the worker thread to step the progress meter
to a particular value.
/// </summary>
/// <param name="val"></param>
public void StepTo( int val )
{
Invoke( new StepToInvoker( DoStepTo ), new object[] { val } );
}


/// <summary>
/// If this property is true, then you should abort work
/// </summary>
public bool IsAborting
{
get
{
return abortEvent.WaitOne( 0, false );
}
}

/// <summary>
/// Call this method from the worker thread to finalize the progress
meter
/// </summary>
public void End()
{
if( requiresClose )
{
Invoke( new MethodInvoker( DoEnd ) );
}
}
#endregion

#region Implementation members invoked on the owner thread
private void DoSetText( String text )
{
label.Text = text;
}

private void DoIncrement( int val )
{
progressBar.Increment( val );
UpdateStatusText();
}

private void DoStepTo( int val )
{
progressBar.Value = val;
UpdateStatusText();
}

private void DoBegin( int minimum, int maximum )
{
DoBegin();
DoSetRange( minimum, maximum );
}

private void DoBegin()
{
cancelButton.Enabled = true;
ControlBox = true;
}

private void DoSetRange( int minimum, int maximum )
{
progressBar.Minimum = minimum;
progressBar.Maximum = maximum;
progressBar.Value = minimum;
titleRoot = Text;
}

private void DoEnd()
{
Close();
}
#endregion

#region Overrides
/// <summary>
/// Handles the form load, and sets an event to ensure that
/// intialization is synchronized with the appearance of the form.
/// </summary>
/// <param name="e"></param>
protected override void OnLoad(System.EventArgs e)
{
base.OnLoad( e );
ControlBox = false;
initEvent.Set();
}

/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}

/// <summary>
/// Handler for 'Close' clicking
/// </summary>
/// <param name="e"></param>
protected override void
OnClosing(System.ComponentModel.CancelEventArgs e)
{
requiresClose = false;
AbortWork();
base.OnClosing( e );
}
#endregion

#region Implementation Utilities
/// <summary>
/// Utility function that formats and updates the title bar text
/// </summary>
private void UpdateStatusText()
{
Text = titleRoot + String.Format( " - {0}% complete",
(progressBar.Value * 100 ) / (progressBar.Maximum - progressBar.Minimum)
);
}

/// <summary>
/// Utility function to terminate the thread
/// </summary>
private void AbortWork()
{
abortEvent.Set();
}
#endregion

#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.progressBar = new System.Windows.Forms.ProgressBar();
this.label = new System.Windows.Forms.Label();
this.cancelButton = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// progressBar
//
this.progressBar.Anchor = ((System.Windows.Forms.AnchorStyles.Bottom
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right);
this.progressBar.Location = new System.Drawing.Point(8, 80);
this.progressBar.Name = "progressBar";
this.progressBar.Size = new System.Drawing.Size(192, 23);
this.progressBar.TabIndex = 1;
//
// label
//
this.label.Anchor = (((System.Windows.Forms.AnchorStyles.Top |
System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right);
this.label.Location = new System.Drawing.Point(8, 8);
this.label.Name = "label";
this.label.Size = new System.Drawing.Size(272, 64);
this.label.TabIndex = 0;
this.label.Text = "Starting operation...";
//
// cancelButton
//
this.cancelButton.Anchor = (System.Windows.Forms.AnchorStyles.Bottom
| System.Windows.Forms.AnchorStyles.Right);
this.cancelButton.DialogResult =
System.Windows.Forms.DialogResult.Cancel;
this.cancelButton.Enabled = false;
this.cancelButton.Location = new System.Drawing.Point(208, 80);
this.cancelButton.Name = "cancelButton";
this.cancelButton.TabIndex = 2;
this.cancelButton.Text = "Cancel";
//
// ProgressWindow
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(290, 114);
this.Controls.AddRange(new System.Windows.Forms.Control[] {
this.cancelButton,
this.progressBar,
this.label});
this.FormBorderStyle =
System.Windows.Forms.FormBorderStyle.FixedDialog;
this.MaximizeBox = false;
this.Name = "ProgressWindow";
this.StartPosition =
System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "ProgressWindow";
this.ResumeLayout(false);

}
#endregion


}
}
 
M

Mike P

Continued...

if (oMsg.SenderName.IndexOf("'") != -1)
// {
// string strSenderName2 =
oMsg.SenderName.Replace("'", "''");

// strInsertQuery = "INSERT INTO SeedingResults
(ReceivedByName, SenderName, ReceivedTime, Subject) VALUES ('" +
oMsg.ReceivedByName.ToString() + "','" + strSenderName2 + "','" +
oMsg.ReceivedTime.ToString() + "','" + oMsg.Subject.ToString() + "')";
// }
// else
// {
// strInsertQuery = "INSERT INTO SeedingResults
(ReceivedByName, SenderName, ReceivedTime, Subject) VALUES ('" +
oMsg.ReceivedByName.ToString() + "','" + oMsg.SenderName.ToString() +
"','" + oMsg.ReceivedTime.ToString() + "','" + oMsg.Subject.ToString() +
"')";
// }
//}

////write to database
//SqlCommand objInsertCommand = new
SqlCommand(strInsertQuery, objConn);

//try
//{
//objConn.Open();

//objInsertCommand.ExecuteNonQuery();

//objConn.Close();
//}
//catch
//{
// throw new DatabaseException();
//}

//move record to archive folder
//oMsg.Move(destfolder);
// }
//}

//dataGridView1.DataSource = dt;
//GridView1.DataSource = dt;
//GridView1.DataBind();

//Log off
oNS.Logoff();

//Clean up
oApp = null;
oNS = null;
oItems = null;
//oMsg = null;

//inform user of success
lblStatus.ForeColor = System.Drawing.Color.Blue;
lblStatus.Text = "**Inbox messages successfully
transferred**";
}
catch (LogonException le)
{
lblStatus.ForeColor = System.Drawing.Color.Red;
lblStatus.Text = "**Outlook Logon Error**";
}
catch (MissingFolderException mfe)
{
lblStatus.ForeColor = System.Drawing.Color.Red;
lblStatus.Text = "**Please create Archive folder within
local Inbox folder**";
}
catch (NoMessagesException nme)
{
lblStatus.ForeColor = System.Drawing.Color.Red;
lblStatus.Text = "**There are no messages in the local
Inbox to be transferred**";
}
catch (DatabaseException se)
{
lblStatus.ForeColor = System.Drawing.Color.Red;
lblStatus.Text = "**Database Error**";
}
catch( System.Threading.ThreadAbortException )
{
// We want to exit gracefully here (if we're lucky)
}
catch( System.Threading.ThreadInterruptedException )
{
// And here, if we can
}
catch
{
lblStatus.ForeColor = System.Drawing.Color.Red;
lblStatus.Text = "**General Exception**";
}
finally
{
if (callback != null)
{
callback.End();
}
}
}

private void MoveMail(Outlook.Items col, Outlook.MAPIFolder
destfolder, SqlConnection objConn)
{
string strInsertQuery = "";

for (int i = 1; i < col.Count + 1; i++)
{
if (col.Item(i) is Outlook.MailItem)
{
Outlook.MailItem oMsg =
(Outlook.MailItem)col.Item(i);

//subject
if ((oMsg.Subject == null) || (oMsg.Subject == ""))
{
oMsg.Subject = "blank";
}
else
{
//escape quotes in subject
oMsg.Subject = oMsg.Subject.Replace("'", "''");
}

if (oMsg.ReceivedByName == null)
{
if (oMsg.SenderName.IndexOf("'") != -1)
{
string strSenderName =
oMsg.SenderName.Replace("'", "''");

strInsertQuery = "INSERT INTO SeedingResults
(SenderName, ReceivedTime, Subject) VALUES ('" + strSenderName + "','" +
oMsg.ReceivedTime.ToString() + "','" + oMsg.Subject.ToString() + "')";
}
else
{
strInsertQuery = "INSERT INTO SeedingResults
(SenderName, ReceivedTime, Subject) VALUES ('" +
oMsg.SenderName.ToString() + "','" + oMsg.ReceivedTime.ToString() +
"','" + oMsg.Subject.ToString() + "')";
}
}
else
{
if (oMsg.SenderName.IndexOf("'") != -1)
{
string strSenderName2 =
oMsg.SenderName.Replace("'", "''");

strInsertQuery = "INSERT INTO SeedingResults
(ReceivedByName, SenderName, ReceivedTime, Subject) VALUES ('" +
oMsg.ReceivedByName.ToString() + "','" + strSenderName2 + "','" +
oMsg.ReceivedTime.ToString() + "','" + oMsg.Subject.ToString() + "')";
}
else
{
strInsertQuery = "INSERT INTO SeedingResults
(ReceivedByName, SenderName, ReceivedTime, Subject) VALUES ('" +
oMsg.ReceivedByName.ToString() + "','" + oMsg.SenderName.ToString() +
"','" + oMsg.ReceivedTime.ToString() + "','" + oMsg.Subject.ToString() +
"')";
}
}

//write to database
SqlCommand objInsertCommand = new
SqlCommand(strInsertQuery, objConn);

try
{
objInsertCommand.ExecuteNonQuery();
}
catch
{
throw new DatabaseException();
}

oMsg.Move(destfolder);
}
}
}
}
}
 
M

Mike P

Continued...

IProcessCallback.cs :

using System;

namespace WindowsApplication1
{
/// <summary>
/// This defines an interface which can be implemented by UI
elements
/// which indicate the progress of a long operation.
/// (See ProgressWindow for a typical implementation)
/// </summary>
public interface IProgressCallback
{
/// <summary>
/// Call this method from the worker thread to initialize
/// the progress callback.
/// </summary>
/// <param name="minimum">The minimum value in the progress
range (e.g. 0)</param>
/// <param name="maximum">The maximum value in the progress
range (e.g. 100)</param>
void Begin(int minimum, int maximum);

/// <summary>
/// Call this method from the worker thread to initialize
/// the progress callback, without setting the range
/// </summary>
void Begin();

/// <summary>
/// Call this method from the worker thread to reset the range
in the progress callback
/// </summary>
/// <param name="minimum">The minimum value in the progress
range (e.g. 0)</param>
/// <param name="maximum">The maximum value in the progress
range (e.g. 100)</param>
/// <remarks>You must have called one of the Begin() methods
prior to this call.</remarks>
void SetRange(int minimum, int maximum);

/// <summary>
/// Call this method from the worker thread to update the
progress text.
/// </summary>
/// <param name="text">The progress text to display</param>
/// <remarks>You must have called one of the Begin() methods
prior to this call.</remarks>
void SetText(String text);

/// <summary>
/// Call this method from the worker thread to increase the
progress counter by a specified value.
/// </summary>
/// <param name="val">The amount by which to increment the
progress indicator</param>
/// <remarks>You must have called one of the Begin() methods
prior to this call.</remarks>
void StepTo(int val);

/// <summary>
/// Call this method from the worker thread to step the progress
meter to a particular value.
/// </summary>
/// <param name="val">The value to which to step the
meter</param>
/// <remarks>You must have called one of the Begin() methods
prior to this call.</remarks>
void Increment(int val);

/// <summary>
/// If this property is true, then you should abort work
/// </summary>
/// <remarks>You must have called one of the Begin() methods
prior to this call.</remarks>
bool IsAborting
{
get;
}

/// <summary>
/// Call this method from the worker thread to finalize the
progress meter
/// </summary>
/// <remarks>You must have called one of the Begin() methods
prior to this call.</remarks>
void End();
}
}
 
M

Marc Gravell

IMO, that is a lot of code for a free forum... you may get takers, but
you'd do a *lot* better if you could demonstrate something simple (and
useful to you) but a bit shorter - e.g.

using System;
using System.Windows.Forms;
using System.ComponentModel;
using System.Threading;

class Program {

static void Main() {
Worker worker = new Worker();
using (Form f = new Form()) {
worker.ProgressChanged += delegate(object sender,
ProgressChangedEventArgs args) {
f.BeginInvoke((MethodInvoker)delegate { // switch back
to UI thread to update Text
f.Text = args.ProgressPercentage.ToString() + "%
complete";
});
};
f.Load += delegate { // start the worker on a background
thread at form load
ThreadPool.QueueUserWorkItem(worker.DoWork);
};
Application.Run(f);
}
}
}

class Worker {
public event ProgressChangedEventHandler ProgressChanged;
public void DoWork(object state) {
Random rand = new Random();
for (int i = 0; i < 100; i++) {
Thread.Sleep(rand.Next(750)); // simulate busy
OnProgressChanged(i, state);
}
}
protected void OnProgressChanged(int percent, object state) {
ProgressChangedEventHandler handler = ProgressChanged;
if (handler != null) handler(this, new
ProgressChangedEventArgs(percent, state));
}
}
 
M

Mike P

Apologies, the only bits that are really relevany are in the first 2
posts, the rest are classes copied directly from the example I referred
to. The bit I am having problems with is here :

private void btnGo_Click(object sender, EventArgs e)
{
ProgressWindow progress = new ProgressWindow();
progress.Text = "Work";
System.Threading.ThreadPool.QueueUserWorkItem(new
System.Threading.WaitCallback(DoSomeWork), progress);
progress.ShowDialog();
}

private void DoSomeWork(object status)
{
IProgressCallback callback = status as IProgressCallback;

try
{
Outlook.Application oApp = new
Outlook.ApplicationClass();

//Get MAPI namespace
Outlook.NameSpace oNS = oApp.GetNamespace("mapi");

string strUserName =
System.Environment.UserName.ToString();

try
{
oNS.Logon(strUserName,
System.Reflection.Missing.Value, false, true);
}
catch
{
throw new LogonException();
}

//Get Messages collection of Inbox
Outlook.MAPIFolder oInbox =
oNS.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox);

try
{
Outlook.MAPIFolder destfolderTest =
oInbox.Folders.Item("Archive");
}
catch
{
throw new MissingFolderException();
}

Outlook.MAPIFolder destfolder =
oInbox.Folders.Item("Archive");

Outlook.Items oItems = oInbox.Items;

int intTotalNumberOfItemsInInbox = oItems.Count;

if (intTotalNumberOfItemsInInbox == 0)
throw new NoMessagesException();

//Get unread e-mail messages
//oItems = oItems.Restrict("[Unread] = true");
//int intTotalUnread = oItems.Count;

//DataTable dt = new DataTable();
//DataRow dr;

//dt.Columns.Add("ReceivedByName");
//dt.Columns.Add("SenderName");
//dt.Columns.Add("ReceivedTime");
//dt.Columns.Add("Subject");
//dt.Columns.Add("Body");

//Outlook.MailItem oMsg;
//int i;

//database connection
SqlConnection objConn = new SqlConnection();
objConn.ConnectionString = "server=e2bvsql4\\inst1; user
id=datawriter; password=rover9; database=SurveyResults";

try
{
objConn.Open();
}
catch
{
throw new DatabaseException();
}

//string strInsertQuery = "";

callback.Begin(0, 2);

for (int i = 0; i < oItems.Count; i++)
{
callback.SetText(String.Format("Performing op: {0}",
i));
callback.StepTo(i);

if (callback.IsAborting)
{
return;
}

oItems = oInbox.Items;
MoveMail(oItems, destfolder, objConn);

if (oItems.Count == 1)
{
i = -1;
}
else
{
i = 0;
}
}

objConn.Close();

//Loop through each unread message
//for (i = 1; i < intTotalNumberOfItemsInInbox + 1; i++)
//{
// //check if appointment or meeting request
// if (oItems.Item(i) is Outlook.MailItem)
// {
// oMsg = (Outlook.MailItem)oItems.Item(i);

//dr = dt.NewRow();
//dr["ReceivedByName"] = oMsg.ReceivedByName.ToString();
//dr["SenderName"] = oMsg.SenderName.ToString();
//dr["ReceivedTime"] = oMsg.ReceivedTime.ToString();
//dr["Subject"] = oMsg.Subject.ToString();
//dr["Body"] = oMsg.Body.ToString();
//dt.Rows.Add(dr);

////subject
//if ((oMsg.Subject == null) || (oMsg.Subject == ""))
//{
// oMsg.Subject = "blank";
//}
//else
//{
// //escape quotes in subject
// oMsg.Subject = oMsg.Subject.Replace("'", "''");
//}

//if (oMsg.ReceivedByName == null)
//{
// if (oMsg.SenderName.IndexOf("'") != -1)
// {
// string strSenderName =
oMsg.SenderName.Replace("'", "''");

// strInsertQuery = "INSERT INTO SeedingResults
(SenderName, ReceivedTime, Subject) VALUES ('" + strSenderName + "','" +
oMsg.ReceivedTime.ToString() + "','" + oMsg.Subject.ToString() + "')";
// }
// else
// {
// strInsertQuery = "INSERT INTO SeedingResults
(SenderName, ReceivedTime, Subject) VALUES ('" +
oMsg.SenderName.ToString() + "','" + oMsg.ReceivedTime.ToString() +
"','" + oMsg.Subject.ToString() + "')";
// }
//}
//else
//{
// if (oMsg.SenderName.IndexOf("'") != -1)
// {
// string strSenderName2 =
oMsg.SenderName.Replace("'", "''");

// strInsertQuery = "INSERT INTO SeedingResults
(ReceivedByName, SenderName, ReceivedTime, Subject) VALUES ('" +
oMsg.ReceivedByName.ToString() + "','" + strSenderName2 + "','" +
oMsg.ReceivedTime.ToString() + "','" + oMsg.Subject.ToString() + "')";
// }
// else
// {
// strInsertQuery = "INSERT INTO SeedingResults
(ReceivedByName, SenderName, ReceivedTime, Subject) VALUES ('" +
oMsg.ReceivedByName.ToString() + "','" + oMsg.SenderName.ToString() +
"','" + oMsg.ReceivedTime.ToString() + "','" + oMsg.Subject.ToString() +
"')";
// }
//}

////write to database
//SqlCommand objInsertCommand = new
SqlCommand(strInsertQuery, objConn);

//try
//{
//objConn.Open();

//objInsertCommand.ExecuteNonQuery();

//objConn.Close();
//}
//catch
//{
// throw new DatabaseException();
//}

//move record to archive folder
//oMsg.Move(destfolder);
// }
//}

//dataGridView1.DataSource = dt;
//GridView1.DataSource = dt;
//GridView1.DataBind();

if (callback.IsAborting)
{
return;
}

//Log off
oNS.Logoff();

//Clean up
oApp = null;
oNS = null;
oItems = null;
//oMsg = null;

//inform user of success
//lblStatus.ForeColor = System.Drawing.Color.Blue;
//lblStatus.Text = "**Inbox messages successfully
transferred**";
}
catch (LogonException le)
{
//lblStatus.ForeColor = System.Drawing.Color.Red;
//lblStatus.Text = "**Outlook Logon Error**";
}
catch (MissingFolderException mfe)
{
//lblStatus.ForeColor = System.Drawing.Color.Red;
//lblStatus.Text = "**Please create Archive folder
within local Inbox folder**";
}
catch (NoMessagesException nme)
{
//lblStatus.ForeColor = System.Drawing.Color.Red;
//lblStatus.Text = "**There are no messages in the local
Inbox to be transferred**";
}
catch (DatabaseException se)
{
//lblStatus.ForeColor = System.Drawing.Color.Red;
//lblStatus.Text = "**Database Error**";
}
catch( System.Threading.ThreadAbortException )
{
// We want to exit gracefully here (if we're lucky)
}
catch( System.Threading.ThreadInterruptedException )
{
// And here, if we can
}
catch
{
//lblStatus.ForeColor = System.Drawing.Color.Red;
//lblStatus.Text = "**General Exception**";
}
finally
{
if (callback != null)
{
callback.End();
}
}
}

private void MoveMail(Outlook.Items col, Outlook.MAPIFolder
destfolder, SqlConnection objConn)
{
string strInsertQuery = "";

for (int i = 1; i < col.Count + 1; i++)
{
if (col.Item(i) is Outlook.MailItem)
{
Outlook.MailItem oMsg =
(Outlook.MailItem)col.Item(i);

//subject
if ((oMsg.Subject == null) || (oMsg.Subject == ""))
{
oMsg.Subject = "blank";
}
else
{
//escape quotes in subject
oMsg.Subject = oMsg.Subject.Replace("'", "''");
}

if (oMsg.ReceivedByName == null)
{
if (oMsg.SenderName.IndexOf("'") != -1)
{
string strSenderName =
oMsg.SenderName.Replace("'", "''");

strInsertQuery = "INSERT INTO SeedingResults
(SenderName, ReceivedTime, Subject) VALUES ('" + strSenderName + "','" +
oMsg.ReceivedTime.ToString() + "','" + oMsg.Subject.ToString() + "')";
}
else
{
strInsertQuery = "INSERT INTO SeedingResults
(SenderName, ReceivedTime, Subject) VALUES ('" +
oMsg.SenderName.ToString() + "','" + oMsg.ReceivedTime.ToString() +
"','" + oMsg.Subject.ToString() + "')";
}
}
else
{
if (oMsg.SenderName.IndexOf("'") != -1)
{
string strSenderName2 =
oMsg.SenderName.Replace("'", "''");

strInsertQuery = "INSERT INTO SeedingResults
(ReceivedByName, SenderName, ReceivedTime, Subject) VALUES ('" +
oMsg.ReceivedByName.ToString() + "','" + strSenderName2 + "','" +
oMsg.ReceivedTime.ToString() + "','" + oMsg.Subject.ToString() + "')";
}
else
{
strInsertQuery = "INSERT INTO SeedingResults
(ReceivedByName, SenderName, ReceivedTime, Subject) VALUES ('" +
oMsg.ReceivedByName.ToString() + "','" + oMsg.SenderName.ToString() +
"','" + oMsg.ReceivedTime.ToString() + "','" + oMsg.Subject.ToString() +
"')";
}
}

//write to database
SqlCommand objInsertCommand = new
SqlCommand(strInsertQuery, objConn);

try
{
objInsertCommand.ExecuteNonQuery();
}
catch
{
throw new DatabaseException();
}

oMsg.Move(destfolder);
}
}
}

I'm not sure where to put the threading code as I have 2 loops that
perform the majority of the work.
 
J

Jon Skeet [C# MVP]

Apologies, the only bits that are really relevany are in the first 2
posts, the rest are classes copied directly from the example I referred
to. The bit I am having problems with is here :

<snip>

That's still a lot of code to go through. It would be better to
present something as short as possible but still complete and
demonstrating the problem.

See http://pobox.com/~skeet/csharp/complete.html

Jon
 
J

Jon Skeet [C# MVP]

Mike P said:
I am trying to write my first program using threading..

In that case I'd strongly recommend against using a GUI at all.

My threading pages give mostly examples which don't have a GUI,
precisely because in WinForms there are extra rules you have to obey,
and it's useful to be able to learn the basics without those extra
rules.

See http://pobox.com/~skeet/csharp/threads
 

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