Need help figuring out why my code is not thread safe

EDN Admin

Well-known member
Joined
Aug 7, 2010
Messages
12,794
Location
In the Machine
I have a main worker thread that runs on a clock loop every 3 seconds. Its main purpose is to constantly check for new emails in an sql server along with any new instant messages. When I break into code it seems to only get a few lines past the Start() method
then sporadically jumps back to the Start() method and consequently does the same thing over and over again. All the while it seems to jump back to the last place the previous thread left off and run another few lines before going back to Start() again. I
have encompassed the start method with an if(!thread.isalive()) then run the thread but im not sure what is not working here.

<pre class="prettyprint public class MainWorkerThread
{
private int NumOfThreadRuns = 0;

private System.Threading.Thread Worker;
private System.Timers.Timer Clock;

public delegate void EmailRecieved(oEmail Sender, EventArgs E);
public static event EmailRecieved OnEmailRecieved; //event that gets raised when new email is recieved

public delegate void InstantMessageRecieved(InstantMessage Sender, EventArgs E);
public static event InstantMessageRecieved OnInstantMessageRecieved;

public delegate void AllImsSorted(object sender, EventArgs E);
public static event AllImsSorted OnAllImsSorted;

public MainWorkerThread()
{
Clock = new System.Timers.Timer();
Clock.Interval = 3000; //clock will fire every 3 seconds
Clock.Elapsed += new System.Timers.ElapsedEventHandler(Clock_Elapsed);
Worker = new System.Threading.Thread(StartThread);
Clock.Start();
}

void Clock_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
if (!Worker.IsAlive) //only re-run the thread if it is no longer alive
{
Worker.Start();
NumOfThreadRuns++;
}
}

void StartThread()
{
//step1: cycle for emails

//the first time it runs it will download all emails without notifying the user of each respective
//unread email
if (NumOfThreadRuns == 1)
{
RetrieveFirstRunEmailsRecieved();
}
//after the thread has ran once. The user will now be notified for any new email that comes in
//respectively
else
{
GetAnyNewEmails();
}
//step2: cycle for ims

if (csProgramTriggers.ImWindowOpen == true)
{
List<InstantMessage> Ims = MessagePool.queAllMesseges();
if (Ims.Count > 0) //proceed only if user has recieved a new message
{
FilterAndOrganizeActiveIms(Ims);
}

if (OnAllImsSorted != null) //this raises an event that signals all ims have been organized
OnAllImsSorted(new object(), new EventArgs()); //subscribed im windows may now arrange
} //their new messages by date and post them
}

/// <summary>
/// Distinguishes if an Im belongs to an active conversation. If it does not, it creates the convo
/// and adds the new message to it. If it does exists it sends the convo and message to FilterNewIms()
/// which distinguishes if the im is new to the conversation in question.
/// </summary>
/// <param name="Ims </param>
void FilterAndOrganizeActiveIms(List<InstantMessage> Ims)
{
foreach (InstantMessage M in Ims)
{
var x = from l in ImCache.ActiveConvos
where l.SenderUserName == M.SenderUserName
select l;

int Count = x.Count(p => p.SenderUserName == M.SenderUserName); //predicates ::)

if (Count == 0) //Conversation is new, take approprate actions
{
AddNewConversation(M);
}

else //conversation already exists. If the IM is new, add it.
{
foreach (ImConversation c in x)
{
FilterNewIms(c, M);
break;
}
}



}
}

/// <summary>
/// Distinguishes if the im is new to the conversation in question. If not it does not add it to the
/// thread. Otherwise it adds it and signals via event.
/// </summary>
/// <param name="C </param>
/// <param name="M </param>
void FilterNewIms(ImConversation C, InstantMessage M)
{
//filter out new ims and raise event
bool Exists = ImCache.ActiveConvos.Find(P => P.SenderUserName == C.SenderUserName).Log.Exists(m => m.InstantMessageID
== M.InstantMessageID);

if (Exists == false)
{
ImCache.ActiveConvos.Find(P => P.SenderUserName == C.SenderUserName).Log.Add(M);

if (OnInstantMessageRecieved != null) //Raise event that passes the new instant message
{
OnInstantMessageRecieved(M, new EventArgs());
}
}
}

/// <summary>
/// Simple method that adds a new conversation to the ImCache. This code is abstracted from FilterAnd
/// OrganizeActiveIms() method for clarity.
/// </summary>
/// <param name="M </param>
void AddNewConversation(InstantMessage M)
{
ImConversation Convo = new ImConversation();
Convo.SenderUserName = M.SenderUserName;
Convo.Log.Add(M);

if (OnInstantMessageRecieved != null) //raises event to notify a new IM was just recieved.
{
OnInstantMessageRecieved(M, new EventArgs());
}
}

/// <summary>
/// Retrieves a list of all emails currently attatched to the current user and filters them according to
/// read state and importance. They are added to the EmailCache class. Use this method only on a
/// constructor because it filters ALL emails. It does not distinguish single emails.
/// </summary>
void RetrieveFirstRunEmailsRecieved()
{
List<oEmail> Recieved = new List<oEmail>();
Recieved = csEmailClass.GetEmails(LogOnProfile.intUserID);

foreach(oEmail E in Recieved)
{
if (E.Read == 0) //if unread
{
EmailCache.Unread.Add(E);
}

if (E.Read == 1)
{
EmailCache.Read.Add(E);
}

if (E.Important == 1)
{
EmailCache.Important.Add(E);
}

//Sent emails do not get filtered here. Only recieved
}
}

/// <summary>
/// Gets all recieved emails, filters through them for any that have not been inboxed nor read yet
/// and then raises an event with the target email
/// </summary>
void GetAnyNewEmails()
{
List<oEmail> Recieved = new List<oEmail>();
Recieved = csEmailClass.GetEmails(LogOnProfile.intUserID);

foreach (oEmail E in Recieved)
{
if (!EmailCache.Unread.Contains(E) & E.Read == 0)
{
EmailCache.Unread.Add(E);
if (OnEmailRecieved != null)
OnEmailRecieved(E, new EventArgs());
}
}
}


}[/code]
<br/>


View the full article
 
Back
Top