VBForums >
.NET >
C# > [RESOLVED] Make Timer run operation in the Background
Click to See Complete Forum and Search --> : [RESOLVED] Make Timer run operation in the Background
daimous
Oct 19th, 2006, 05:07 AM
hi guys! is ther anyway for me to make my Timer_Tick eventhandler run operation in the Background becuase the eventhandler perform a lot of task and time consuming that cause my User Interface to seem as though it has stopped responding while they(The code under the Timer_Tick EventHandler) are running. Will guys please help me with this. Thanks in advance!
jmcilhinney
Oct 19th, 2006, 06:13 AM
I'd suggest not using a single BackgroundWorker if you need more than one worker thread running at a time. You could write your event handlers ahead of time and then in your Timer's event handler you create a new BackgroundWorker, attach it to the appropriate event handlers and then run it.
daimous
Oct 20th, 2006, 02:00 AM
Sorry, i think i explain my problem i lil vague..becuase what i want is, Is to run any code under Timer_Tick eventhandler in Background becuase that is where delays happen which cause my User Interface to seem as though it has stopped responding. Maybe i'll just remove the code above becuase that makes my question vague.
popskie
Oct 20th, 2006, 02:07 AM
use thread
jmcilhinney
Oct 20th, 2006, 02:16 AM
There was nothing wrong with your explanation. I'm saying that each time the Timer Ticks you create a BackgroundWorker and send it on its way. If your Timer Ticks again before that backgroundWorker has finished its task there's no issue because you won't be trying to use it again:Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
'Create a new worker.
Dim worker As New System.ComponentModel.BackgroundWorker
'Attach the appropriate event handlers.
AddHandler worker.DoWork, AddressOf BackgroundWorker_DoWork
AddHandler worker.RunWorkerCompleted, AddressOf BackgroundWorker_RunWorkerCompleted
'Set the worker to work.
worker.RunWorkerAsync()
End Sub
Private Sub BackgroundWorker_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs)
'Perform long-running operation here.
End Sub
Private Sub BackgroundWorker_RunWorkerCompleted(ByVal sender As Object, _
ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs)
'A worker has just completed its work so dispose it.
DirectCast(sender, System.ComponentModel.BackgroundWorker).Dispose()
End Sub
jmcilhinney
Oct 20th, 2006, 02:21 AM
Actually, you may need to keep a reference to the BackgroundWorker as well so that it doesn't get cleaned up by the garbage collector:Private workers As New List(Of System.ComponentModel.BackgroundWorker)
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
'Create a new worker.
Dim worker As New System.ComponentModel.BackgroundWorker
'Attach the appropriate event handlers.
AddHandler worker.DoWork, AddressOf BackgroundWorker_DoWork
AddHandler worker.RunWorkerCompleted, AddressOf BackgroundWorker_RunWorkerCompleted
'Add the worker to the list of active workers so it is not released to the garbage collector.
Me.workers.Add(worker)
'Set the worker to work.
worker.RunWorkerAsync()
End Sub
Private Sub BackgroundWorker_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs)
'Perform long-running operation here.
End Sub
Private Sub BackgroundWorker_RunWorkerCompleted(ByVal sender As Object, _
ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs)
Dim worker As System.ComponentModel.BackgroundWorker = DirectCast(sender, System.ComponentModel.BackgroundWorker)
'A worker has just finished its work so destroy it and release it to the garbage collector.
Me.workers.Remove(worker)
worker.Dispose()
End Sub
daimous
Oct 20th, 2006, 04:00 AM
Thanks dude! But the thing that Im trying to implement is a little different from the code you give me. actually, what im trying to do is to perform long-running operation each time Timer Ticks so the long-running operation should be under Timer1_Tick Eventhandler and Timer_Tick is the one i will call from the BackgroundWorker_DoWork. In other words I will place the long-running operation under Timer1_Tick and Timer1_Tick under BackgroundWorker_DoWork but im not sure is this is posible and if it is the right way.
jmcilhinney
Oct 20th, 2006, 04:15 AM
That makes no sense I'm afraid. You don't call the Timer's Tick event handler. It is invoked automatically when the Timer raises its Tick event. The Timer Ticks when it Ticks. Each time it Ticks you want to perform a long-running operation, correct? If so then you create a BackgroundWorker on each Tick and it goes off and performs the long-running operation. Anything else is simply not logical.
daimous
Oct 20th, 2006, 04:28 AM
Thanks! that make things more clear to me..thanks again..i'll just try to use the code you give me.
jmcilhinney
Oct 20th, 2006, 04:49 AM
Note also that it's only worth using the BackgroundWorker if you need to use either its ProgressChanged and/or RunWorkerComplete events. If there's nothing specific that you need to do in the main thread when each worker has finished then you may as well take popskie's advice and just create a Thread object explicitly as it is easier. The BackgroundWorker is advantageous when you need to communicate with the main thread from the worker thread or if you want to use the same component multiple times to run a background task. If you're not doing either of those things then using the BackgroundWorker isn't worth the effort.
daimous
Oct 22nd, 2006, 07:33 PM
I have tried to use the Thread but its just the same my form stop each time the timer_ ticks...but i dunno if i implement it right will you please check it. Thanks!
private void Alarm_timer_Tick(object sender, EventArgs e)
{
Thread thread_GetEvents = new Thread(new ThreadStart(GetEvents));
thread_GetEvents.Start();
thread_GetEvents.Join();
}
private void GetEvents()
{
List_Service.Lists listService = new List_Service.Lists();
listService.Credentials = new NetworkCredential("username", "password", "domain");
listService.PreAuthenticate = true;
XmlDocument xmlDoc = new System.Xml.XmlDocument();
XmlNode ndQuery = xmlDoc.CreateNode(XmlNodeType.Element, "Query", "");
XmlNode ndViewFields = xmlDoc.CreateNode(XmlNodeType.Element, "ViewFields", "");
XmlNode ndQueryOptions = xmlDoc.CreateNode(XmlNodeType.Element, "QueryOptions", "");
ndQueryOptions.InnerXml = "<IncludeMandatoryColumns>FALSE</IncludeMandatoryColumns>" +
"<DateInUtc>FALSE</DateInUtc>";
ndQuery.InnerXml = "<Where><And><IsNotNull><fieldRef Name='Alarm'/></IsNotNull>" +
"<IsNotNull><fieldRef Name='Alarm_x0020_For'/></IsNotNull>" +
"</And></Where>";
try
{
XmlNode ndListItems = listService.GetListItems("Events", null, ndQuery, null, null, ndQueryOptions);
GetItems(ndListItems);
}
catch (System.Web.Services.Protocols.SoapException ex)
{
MessageBox.Show("Message:\n" + ex.Message + "\nDetail:\n" + ex.Detail.InnerText +
"\nStackTrace:\n" + ex.StackTrace + "\n\nPlease contact your administrators.", "BCMD");
Alarm_timer.Stop();
}
}
private void GetItems(XmlNode xmlFragment)
{
XmlNamespaceManager nsManager = new XmlNamespaceManager(xmlFragment.OwnerDocument.NameTable);
nsManager.AddNamespace("s", "uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882");
nsManager.AddNamespace("dt", "uuid:C2F41010-65B3-11d1-A29F-00AA00C14882");
nsManager.AddNamespace("rs", "urn:schemas-microsoft-com:rowset");
nsManager.AddNamespace("z", "#RowsetSchema");
nsManager.AddNamespace("", "http://schemas.microsoft.com/sharepoint/soap/");
XmlNodeList rowNodes = xmlFragment.SelectNodes("rs:data/z:row", nsManager);
foreach (XmlNode rowNode in rowNodes)
{
DateTime EvntDate = new DateTime();
DateTime AlarmDate = new DateTime();
DateTime DateNow = new DateTime();
string Alarm_Id;
string EvntTitle;
string EvntLocation;
string AlarmFor;
AlarmFor = rowNode.Attributes.GetNamedItem("ows_Alarm_x0020_For").InnerText.ToUpper();
EvntDate = DateTime.Parse(rowNode.Attributes.GetNamedItem("ows_EventDate").InnerText);
AlarmDate = DateTime.Parse(rowNode.Attributes.GetNamedItem("ows_Alarm").InnerText);
DateNow = DateTime.Now;
AlarmDate).ToString());
if (AlarmDate.ToShortDateString() == DateNow.ToShortDateString())
{
if (AlarmDate.ToShortTimeString() == DateNow.ToShortTimeString())
{
Alarm_Id = rowNode.Attributes.GetNamedItem("ows_ID").InnerText.ToString();
if (lstAlarmDump.FindStringExact(Alarm_Id) == ListBox.NoMatches)
{
lstAlarmDump.Items.Add(Alarm_Id);
//MessageBox.Show("ID : " + Alarm_Id + " EVENT:" + rowNode.Attributes.GetNamedItem("ows_LinkTitle").InnerText.ToString());
EvntTitle = rowNode.Attributes.GetNamedItem("ows_LinkTitle").InnerText.ToString();
EvntLocation = rowNode.Attributes.GetNamedItem("ows_Location").InnerText.ToString();
show_Alarm_notification(EvntTitle,EvntDate.ToString(),EvntLocation);
//MessageBox.Show("ALARM FOR" + AlarmFor);
}
}
}
}
}
public void show_Alarm_notification(string ArgEvntTitle, string ArgEvntDate, string ArgEvntLocation)
{
int notification_y_coor;
Rectangle workingArea = Screen.PrimaryScreen.WorkingArea;
Alarm_data EvntData = new Alarm_data();
EvntData.EvntTitle = ArgEvntTitle;
EvntData.EvntDate = ArgEvntDate;
EvntData.EvntLocation = ArgEvntLocation;
SoundPlayer sndAlarm = new SoundPlayer();
Notification Notification_frm = new Notification();
Notification_frm.ParentData = EvntData;
Notification_frm.TopMost = true;
Notification_frm.StartPosition = FormStartPosition.Manual;
notification_y_coor = workingArea.Height;
//workingArea.Height - Notification_frm.Height;
//MessageBox.Show("TITLE: " + EvntTitle + " Date: " + EvntDate + " Location: " + EvntLocation);
Notification_frm.Show();
for (int x = 0; x <= Notification_frm.Height; x++)
{
Notification_frm.Location = new Point(workingArea.Width - Notification_frm.Width, workingArea.Height - x);
}
if (File.Exists(txtSettingSoundFile.Text))
{
sndAlarm.SoundLocation = txtSettingSoundFile.Text;
}
else
{
sndAlarm.Stream = Properties.Resources.WARNING;
}
sndAlarm.Play();
}
jmcilhinney
Oct 22nd, 2006, 08:03 PM
Of course your form freezes. You're calling Join on the new Thread. Have you read what Join does? It blocks the current thread until the thread jou're joining completes.
daimous
Oct 22nd, 2006, 09:06 PM
opppppsss!!! sorry i forgot to remove the join..but im just wondering why my notification form that i show in "show_Alarm_notification" notification method is automatically closed or it disappear and if that will be the case my alarm notification will be useless...whats wrong?
jmcilhinney
Oct 22nd, 2006, 09:34 PM
I posted previously that it is only worth using a BackgroundWorker if you need to use its ProgressChanged or RunWorkerComplete events. Basically that means if you want to notify the UI thread of something during execution of the worker thread (ProgressChanged) or when execution of the worker thread completes (RunWorkerComplete). If you're trying to use a MessageBox then it sounds a lot like your trying to notify the UI of something, so the BackgroundWorker is appropriate.
If you display a MessageBox directly from a worker thread then it is NOT displayed as a modal dialogue of the main form. That's because the two forms' handles are owned by different threads. A MessageBox displayed from a worker thread will NOT prevent the user accessing any form not also created on that same worker thread. To make it prevent access to your main form you would need to use delegate to invoke a method on the UI thread. THAT is why you would use a BackgroundWorker. It's ProgressChanged and RunWorkerComplete events are raised in the UI thread so explicit delegation is not required. That's the whole reason for the BackgroundWorker's existence.
daimous
Oct 22nd, 2006, 10:03 PM
ohhh...so i really need to use BackgroundWorker..but im heaving a little with this line of code you posted above becuase when i try to convert it to C#, using the converter from your signature, it has an error. is there something wrong the code below? is "Of" really needed?
Private workers As New List(Of System.ComponentModel.BackgroundWorker)
jmcilhinney
Oct 22nd, 2006, 10:22 PM
Ah, sorry. I forget that I'm in the C# forum sometimes when I get here via my UserCP. You should have said something. The way to create a generic List in C# is:private List<System.ComponentModel.BackgroundWorker> workers = new List<System.ComponentModel.BackgroundWorker>();
daimous
Oct 23rd, 2006, 01:52 AM
its ok...Maybe next time i will.. ;) Thanks for all the help anyway.
vbforums.com
Copyright Internet.com Inc., All Rights Reserved.