I cant figure out how to proceed the best way with this problem.
Right now I have a windows service which only task is to gather data from a database with a specific DSN and then send out an email if the data is valid. The service contains a timer which ticks every 5 minuts and performs the tasks above.
Now I need to re-write the windows service to be able to run on more than 1 DSN.
I was thinking of making several threads inside the windows service and then again have a seperat timer inside each thread.
Is this a good idea and how can this be done? I want to avoid having a windows service for each DSN.
Ill try to draw it if I dont make any sense
Windows Service
Thread1(DSN1)-----------------------------Thread2(DSN2)----------------------Thread3(DSN3)
Timer(ticks every X minuts)-----------------Timer(same)-------------------------Timer(same)
Logic()---------------------------------------------Logic---------------------------------Logic()
Hope my problem makes sense :)
As far as I Know each timer represents a thread on its own. Knowing this, I would try to dynamically create timer objects for each given dsn.
public partial class Service1 : ServiceBase
{
public Service1()
{
InitializeComponent();
}
private List<GetDataFromDSN> list = null;
protected override void OnStart(string[] args)
{
list = new List<GetDataFromDSN>();
// assume args contains your given dsn values
foreach (string dsn in args)
{
GetDataFromDSN newObj = new GetDataFromDSN();
newObj.DSN = dsn;
list.Add(newObj);
newObj.Start();
}
}
}
public class GetDataFromDSN
{
public string DSN { get; set; }
private Timer timer = null;
private double interval = 1000*60*5; // 5 minutes interval
public GetDataFromDSN()
{
// init your object
timer = new Timer(interval);
timer.Elapsed +=new ElapsedEventHandler(timer_Elapsed);
}
private void timer_Elapsed(object sender, ElapsedEventArgs e)
{
// do what ever you want
}
public void Start() // or even make timer public
{
timer.Start();
}
public void Stop()
{
timer.Stop();
}
}
Do each of the DSNs need to be on a separate Thread?
If you were to encapsulate the Email retrieval and validation logic within some sort of service that the Thread invoked, the fact that there were multiple DSNs could be hidden from the scheduling thread. For instance, an IEmailService might have the following contract:
public interface IEmailService
{
void SendEmailsToValidAddresses();
}
and the implementation might look something like this:
public class MultipleSourcesEmailService : IEmailService
{
private IEnumerable<IDatabaseSource> databases;
public EmailService(params IDatabaseSource[] sources)
{
databases = new List<IDatabaseSource>(sources);
}
public void SendEmailsToValidAddresses()
{
foreach(var database in databases)
{
var emailAddresses = database.SelectAllEmailAddresses();
ValidateAndSendEmailsTo(emailAddresses);
}
}
public void ValidateAndSendEmailsTo(IEnumerable<string> emailAddresses)
{
// Perform appropriate logic
...
}
}
In this way, your timer logic can remain the same and on a single Thread whilst the concern of sending emails is separated into the IEmailService. This also means that you could implement a SingleSourceEmailService and a MultipleSourceEmailService and swap the multiple sources in when you're code complete and the consumer of the service need never know.
Of course, the EmailService as implemented above will SendEmails from multiple sources sequentially - if you need it to run in parallel you could change the EmailService to kick off a new Thread for each of the DSNs that you have, you could even call it the: MultiThreadedMultipleSourceEmailService but as a consumer of the IEmailService your scheduling will never know the difference.
Use a backgroundworker.
http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx
Just start one for each DSN, very smooth and easy to use.
Try using System.Threading.Timer
Here is sample code from my project, Hope this helps
public void StartDSNTimers()
{
_tmr1 = new Timer(CheckMessages, dsn1, 0, 60000);
_tmr2 = new Timer(CheckMessages, dsn2, 0, 60000);
_tmr3 = new Timer(CheckMessages, dsn3, 0, 60000);
}
private void CheckMessages(object obj)
{
//Logic
}
Related
I'm working on a program and I wanted to know the best way I can get information from one class to another.
My purpose is to get information from MyTimer to the Program class about how much "ticks" the timer did.
** I don't want from the class MyTimer to be dependent on the Program class (Like by using Program.SetUpdate()). MyTimer class should work with every class without changing his code.
I've already tried using public static method to send the information.
class Program
{
private static int _count;
private static MyTimer _myTimer;
static void Main(string[] args)
{
_count = 0;
_myTimer = new MyTimer() { Timer_Interval = 100 };
_myTimer.Start();
do
{
Console.WriteLine("Press q to quit.");
} while (Console.ReadKey().KeyChar.ToString().ToLower() != "q");
_myTimer.Stop();
}
public static void SetUpdate(int count)
{
_count = count;
Print();
}
private static void Print()
{
Console.WriteLine(_count);
}
}
class MyTimer
{
private Timer _timer;
private int _ticks;
public int Timer_Interval { get; set; }
public MyTimer()
{
_timer = new Timer();
_timer.Elapsed += new ElapsedEventHandler(_timer_Elapsed);
}
private void _timer_Elapsed(object sender, ElapsedEventArgs e)
{
Program.SetUpdate(_ticks);
_ticks++;
}
public void Start()
{
if (Timer_Interval == 0)
throw new InvalidOperationException("_timer interval can not be 0.");
_ticks = 0;
_timer.Interval = Timer_Interval;
_timer.Start();
}
public void Stop()
{
_timer.Stop();
}
}
The output is 1,2,3... until you press q/Q
I've tried to do it as simple as I can only to show you the concept.
So I created a class named Program that call MyTimer class.
MyTimer class is simply like a timer: stop,start and elapsed. Each interval it makes a "tick".
You'd normally fix this sort of issue by establishing a "direction". E.g. here it feels natural that it should be "from" Program "to" MyTimer. In that given direction, it's perfectly fine to make direct method calls, access properties, etc.
When you need information to flow in the other direction, that's when you use events. MyTimer raises an event and Program can have a handler. In this way, MyTimer doesn't know which classes are creating it/working with it or even how many event handlers have been installed.
I think Damien nailed it pretty much for this scenario.
Yet, I'd like to propose an alternative: Using a shared State Object.
You could define a State class, which does nothing else than hold the value of the tick-count.
You'd instanciate it in Program and pass it to the MyTimer. Mind that both classes now share the same instance (possibly introducing threading/concurrency issues if in multithreaded context).
MyTimer then would update the state on that shared Object.
Examples are Model/ViewModel classes in MVVM/WPF where you would bind some Control's property to that object's property.
Mind that Program wouldn't know of a occurring change out of the box. So that would have to be handled additionally. Either again via an Event, some "Observer Pattern" or similar.
As I said, events are the way to go here but I thought it couldn't hurt to suggest an alternative way of inter-class communication.
I have a client - server application and I want to check periodically if client has disconnected from server.
I have decided that I will check for incoming packets. If i received any in time span of let say 15 seconds I have a valid connection,
if not I have disconnected and will try to reconnect.
So far I have this sample code (this is sample recreated from my code):
namespace TimerExample
{
class Program
{
static void Main(string[] args)
{
HandlePackets();
}
public void HandlePackets()
{
//code that handles incomming packets
foo test = new foo();
test.StartThread();
}
}
class foo
{
public bool _isRunning { get; set; }
private Stopwatch sw { get; set; }
public void StartThread()
{
this._isRunning = true;
new Thread(new ThreadStart(this.DoWork)).Start();
this.sw.Restart();
}
public void StopThread()
{
this._isRunning = false;
this.sw.Stop();
}
private void DoWork()
{
while (this._isRunning)
{
Console.WriteLine("Elapsed in miliseconds: " + this.GetRuntime().ToString());
if (GetRuntime() > 15000)
{
Console.WriteLine("Client disconnected.... restarting");
this.StopThread();
}
Thread.Sleep(1000);
}
}
public long GetRuntime()
{
return this.sw.ElapsedMilliseconds;
}
public foo()
{
_isRunning = false;
sw = new Stopwatch();
}
}
}
What I want for code to be doing is: Function HandlePackets will be executed every time packet will arrive. Inside that function I will call
function StartThread which will run Stopwatch in separate thread and this process will go on as long as stopwatch elapsed time in milliseconds
won't be bigger than lets say 15 seconds.
If it will I will call Reconnect.
So basically timer will restart every time a packet is received and reconnect will be called if ElapsedTime will be greater than 15 seconds.
There are several ways to implement this mechanism.
Creating thread is the worst one.
Be careful - accessing Stopwatch instance members from multiple threads is not safe.
One easy and straightforward solution is to create ThreadPool Timer that ticks let's say every 15 seconds and checks boolean variable via Volatile.Read. Once boolean variable is False - you can re-connect.
From receiver thread you just need to set variable using Volatile.Write true. This does not consume resources when receiving (almost).
In many of the implementations could be races because of re-connection mechanism that can start a moment before new packet arrives. The easiest and rogue way to improve this is to stop timer right before you decide to re-connect and start it again once connection is done. You must understand that there is no way to solve this false-reconnection issue.
The method above works pretty much like WatchDog
From design perspective I would recommend you create classes : Receiver and WatchDog and ConnectionManager
// Receives and processes data
class Receiver : IDisposable
{
public Receiver(WatchDog watchDog);
public void LoopReceive(); // Tick watch dog on every packet
public void Dispose();
}
// Setups timer and periodically checks if receiver is alive.
// If its not, it asks manager to reconnect and disposes receiver
class WatchDog : IDisposable
{
public WatchDog(ConnectionFactory factory);
// Setups timer, performs Volatile.Read and if receiver is dead, call dispose on it and ask manager to reconnect.
public void StartWatching(IDisposable subject);
public void Tick(); // Volatile.Write
public void Dispose();
}
// Can re-connect and create new instances of timer and watchdog
// Holds instance variable of receiver created
class ConnectionManager
{
public void Connect();
// disposes watch dog and calls connect
public void ReConnect(WatchDog watchDog);
}
PS: Volatile.* could be replaced with volatile keyword for the flag variable
I'm developing an MDI application in C# with .NET 4.0.
Each MDI child will be a form with tabs that contains GroupBoxes with a DataGridView.
I implemented a class that is used to manage Threads.
This is the StartNewThread method in my ThreadManager class
public string StartNewThread(ThreadStart threadMethod, string threadName)
{
try
{
Thread thread = new Thread(() => threadMethod());
thread.Name = threadName + " (" + _threadCount++.ToString("D4") + ")";
thread.Start();
_threadList.Add(thread.Name, thread);
return thread.Name;
}
catch (Exception ex)
{
//Log and manage exceptions
}
return null;
}
To create the DataGridViews I used some Wizard component from Oracle Developer Tools for VS library. So, after creating the DataSource and so the DataSet, then I used drag&drop from DataSource tree to drag tables and automatically create DataGridViews.
This is the actual working code, behind the child form, automatically created.
public partial class ScuoleNauticheForm : Form
{
public ScuoleNauticheForm()
{
InitializeComponent();
}
private void ScuoleNauticheForm_Load(object sender, EventArgs e)
{
// TODO: This line of code loads data into the 'dEVRAC_NauticheDataSet.PERSONALE' table. You can move, or remove it, as needed.
this.PersonaleTableAdapter.Fill(this.DEVRAC_NauticheDataSet.PERSONALE);
// TODO: This line of code loads data into the 'dEVRAC_NauticheDataSet.NATANTI' table. You can move, or remove it, as needed.
this.NatantiTableAdapter.Fill(this.DEVRAC_NauticheDataSet.NATANTI);
// TODO: This line of code loads data into the 'dEVRAC_NauticheDataSet.SCUOLE' table. You can move, or remove it, as needed.
this.ScuoleTableAdapter.Fill(this.DEVRAC_NauticheDataSet.SCUOLE);
}
}
What I want to do now is manage all the load/query/insert/update/delete operations on separated threads. For now I tried to create a new Thread to load the data.
This i what I tried.
public partial class ScuoleNauticheForm : Form
{
private readonly ThreadManager _threadManager;
public ScuoleNauticheForm()
{
InitializeComponent();
_threadManager = ThreadManager.GetInstance();
}
private void ScuoleNauticheForm_Load(object sender, EventArgs e)
{
_threadManager.StartNewThread(LoadData, "LoadData");
}
#region DataBind
private void LoadData()
{
// TODO: This line of code loads data into the 'dEVRAC_NauticheDataSet.PERSONALE' table. You can move, or remove it, as needed.
this.PersonaleTableAdapter.Fill(this.DEVRAC_NauticheDataSet.PERSONALE);
// TODO: This line of code loads data into the 'dEVRAC_NauticheDataSet.NATANTI' table. You can move, or remove it, as needed.
this.NatantiTableAdapter.Fill(this.DEVRAC_NauticheDataSet.NATANTI);
// TODO: This line of code loads data into the 'dEVRAC_NauticheDataSet.SCUOLE' table. You can move, or remove it, as needed.
this.ScuoleTableAdapter.Fill(this.DEVRAC_NauticheDataSet.SCUOLE);
}
#endregion
}
It works only for half... There's no errors or exceptions, but if I load data that way, using a different Thread, the DataGridviews doesn't update and I don't see any data when opening the form, even if I move or resize it. Otherwise, using the automatically generated code, the DataGridViews are populated correctly.
But, since the wizard also add a navigation bar to the form to navigate through records, I noticed that it works, because it counts the correct number of records and I can use the arrows (first, previous, next, last) to move across records.
Here is an image showing my form.
See the navigation bar that is showing the correct number of total records (14) and allows me to navigate through them.
Do I need to use delegates? If so, I think it would be a mess... how many delegates should I create and for those methods? Or is there another solution?
-- UPDATE 1 --
I know that UI threads are automatically managed by .NET and so the programmer don't need to manage them with code. So, should it be a problem of synchronization with the .NET UI thread built in management? Maybe my thread launched by Form.Load() interferes with the UI thread managed by the .NET?
-- UPDATE 2 --
I tried to implement the solution proposed by faby. I replaced my Thread logic with Task logic. The behaviour of the application is the same, so everything that was working with Thread is now working also with Task. But the problem still remains. Since I'm on .NET 4.0 and not .NET 4.5, I could not use async and await. So I don't know if with that approach the UI will work correctly or not.
Any other suggestion valid for .NET 4.0?
do you consider the option of BackgroundWorker Class ?
implementing DoWork and ProgressChanged you can do in DoWork what you are doing in background thread and in ProgressChanged you can update the UI
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
//long running task
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
//update the UI components
}
update 1
another solution could be something like this
public Task LoadDataAsync()
{
return Task.Factory.StartNew( () =>
{
//code to fill your datagridview
});
}
then
public async Task ChangeUIComponents()
{
await LoadDataAsync();
// now here you can refresh your UI elements
}
update 2
to use async/await with framework 4.0 try with this NugetPackage (Microsoft.Bcl.Async)
I finally found a solution without using async/await and other libraries.
The problem was that I was executing the Fill() method of TableAdapter inside a new Task and so I needed to use InvokeRequired to set the binding source data source to the DataTable within the right thread.
So I used delegates. I changed the method called on the new Task and make it call 3 other methods (one for each DataGridView to fill) that call Fill() implementing the InvokeRequired check.
Now I see the creation of the UI and then, after a couple of seconds, the asynchronous filling of the DataGridViews.
This article was useful: Load data from TableAdapter async
Thanks to #faby for the suggestion to use Task instead of Thread. It was not the solution but it is a better way to do Threading.
Here's the final working code.
public partial class ScuoleNauticheForm : Form
{
private readonly TaskManager _taskManager;
public ScuoleNauticheForm()
{
InitializeComponent();
_taskManager = TaskManager.GetInstance();
}
private void ScuoleNauticheForm_Load(object sender, EventArgs e)
{
_taskManager.StartNewTask(LoadData);
}
#region Delegates
public delegate void FillPersonaleCallBack();
public delegate void FillNatantiCallBack();
public delegate void FillScuoleCallBack();
#endregion
#region DataBind
private void LoadData()
{
FillPersonale();
FillNatanti();
FillScuole();
}
public void FillPersonale()
{
if (PersonaleDataGridView.InvokeRequired)
{
FillPersonaleCallBack d = new FillPersonaleCallBack(FillPersonale);
Invoke(d);
}
else
{
this.PersonaleTableAdapter.Fill(this.DEVRAC_NauticheDataSet.PERSONALE);
}
}
public void FillNatanti()
{
if (NatantiDataGridView.InvokeRequired)
{
FillNatantiCallBack d = new FillNatantiCallBack(FillNatanti);
Invoke(d);
}
else
{
this.NatantiTableAdapter.Fill(this.DEVRAC_NauticheDataSet.NATANTI);
}
}
public void FillScuole()
{
if (ScuoleDataGridView.InvokeRequired)
{
FillScuoleCallBack d = new FillScuoleCallBack(FillScuole);
Invoke(d);
}
else
{
this.ScuoleTableAdapter.Fill(this.DEVRAC_NauticheDataSet.SCUOLE);
}
}
#endregion
}
-- Update 1 --
If the methods to call by the new Task are void and without any parameters, you can simplify a bit the above code by using Invoke((MethodInvoker) MethodName). The behaviour of the application is the same.
Here's the simplified version of the code.
public partial class ScuoleNauticheForm : Form
{
private readonly TaskManager _taskManager;
public ScuoleNauticheForm()
{
InitializeComponent();
_taskManager = TaskManager.GetInstance();
}
private void ScuoleNauticheForm_Load(object sender, EventArgs e)
{
_taskManager.StartNewTask(LoadData);
}
#region DataBind
private void LoadData()
{
// Since Fill Methods are void and without parameters,
// you can use the Invoke method without the need to specify delegates.
Invoke((MethodInvoker)FillPersonale);
Invoke((MethodInvoker)FillNatanti);
Invoke((MethodInvoker)FillScuole);
}
public void FillPersonale()
{
this.PersonaleTableAdapter.Fill(this.DEVRAC_NauticheDataSet.PERSONALE);
}
public void FillNatanti()
{
this.NatantiTableAdapter.Fill(this.DEVRAC_NauticheDataSet.NATANTI);
}
public void FillScuole()
{
this.ScuoleTableAdapter.Fill(this.DEVRAC_NauticheDataSet.SCUOLE);
}
#endregion
}
I'm writing a simple Windows forms application to get me into the swing of things with Threads. So far what I have is working, but what I would like to do is contain it all in a seperate class rather than directly in my forms code.
I have a background thread that starts and retrieves data from a database. I then display that data in to a listbox.
private delegate void UpdateListValues(List<ListBoxItem> itemList);
private void form_main_Shown(object sender, EventArgs e)
{
// Set the loading text.
list_selection.Items.Add(ListHelpers.LoadingItem());
// Start the data access on a seperate thread.
Thread worker = new Thread(GetInvoicingData);
worker.IsBackground = true;
worker.Start();
}
private void GetInvoicingData()
{
// Query database
List<ListBoxItem> values = DAC.GetInvoicingAccounts();
// Display results
BeginInvoke(new UpdateListValues(DisplayList), new object[] { values });
}
private void DisplayList(List<ListBoxItem> itemList)
{
// Display each result
list_selection.Items.Clear();
for (int i = 0; i < itemList.Count; i++)
{
list_selection.Items.Add(itemList[i]);
}
}
The problem is that in the DisplayList method, I won't be able to access the list box (list_selection) because it's part of the form class. Does anyone have any suggestions on how I can do this.
Also, I'm new to threading so feel free to tell me I'm doing it absolutely wrong. I just used the example from http://www.codeproject.com/Articles/23517/How-to-Properly-Handle-Cross-thread-Events-and-Upd to get me to where I am now.
Thanks
How about something like this:
// Added the form's class declaration to highlight separation of thread code into a separate class, but may not be exactly the same as yours depending on naming
public class Form1 : Form
{
private readonly DataRetriever _dataRetriever;
private void form_main_Shown(object sender, EventArgs e)
{
// Set the loading text.
list_selection.Items.Add(ListHelpers.LoadingItem());
// Create the DataRetriever, and provide it with a delegate to DisplayList for returning data
_dataRetriever = new DataRetriever(DisplayList);
// Start retrieving data on a separate thread...
_dataRetriever.GetData();
}
private void DisplayList(List<ListBoxItem> itemList)
{
if (InvokeRequired)
{
// Ensure the update occurs on the UI thread
Invoke((Action)(() => DisplayList(itemList)));
return;
}
// Display each result
list_selection.Items.Clear();
foreach (var item in itemList)
{
list_selection.Items.Add(item);
}
}
}
// Separate class to hold thread code
public class DataRetriever
{
public delegate void UpdateCallbackDelegate(List<ListBoxItem> itemList);
private readonly UpdateCallbackDelegate _updateCallback;
public DataRetriever(UpdateCallbackDelegate updateCallback)
{
_updateCallback = updateCallback;
}
public void GetData()
{
var thread = new Thread(GetInvoicingData)
{
IsBackground = true
};
thread.Start();
}
private void GetInvoicingData()
{
// Not sure whether "DAC" is a static class, if it needs to be constructed
// in the DataRetriever's constructor, or passed to it as a parameter
_updateCallback(DAC.GetInvoicingAccounts());
}
}
As you can see, all the thread code is now in a separate class DataRetriever, and a delegate provided when constructing it to enable the retrieved data to be passed back to the form once the retrieval is complete. The method that handles the callback ensures that the call is marshalled to the UI thread to prevent cross-thread exceptions.
I would like to point out that this is not presented as the "best" way to do this, but merely as an answer to the question (how to separating threading code into a separate class). As others have mentioned, there are already mechanisms in place to do this sort of thing (e.g. BackgroundWorker). Some complexity has been omitted for clarity. For example, in the implementation presented here, if you were to call GetData() multiple times (with each call occurring before the previous ones have returned their data), you would have multiple queries occurring simultaneously, and as they are running asynchronously, may return their data in an arbitrary order. This may or may not be an issue in your case.
I have to make a Instant Messenger server in C#. The server is a ConsoleApplication project. And I want to make a server that runs in 3 threads. I will explain in the code below.
The question is how can I invoke a function from a separate thread, or make an event on a separate thread?
This is the main server class.
public class GiNetServer
{
public void Start()
{
netServer = new NetServer();
msgHandler = new NetMsgHandler();
netServer.NewNetMsg += msgHandler.HandleMsg;
Work();
}
private void Work()
{
while(true) //This runs in the MainThread
sleep(1);
}
}
The NetServer class creates 2 Threads: acceptClientsThread and receiveMessagesThread.
The receive thread calls the NewNetMsg.
public class NetServer
{
public event NewNetMsgEventHandler NewNetMsg;
public NetServer()
{
acceptClientsThread = new Thread(ListenForClients);
receiveMessageThread = new Thread(Receive);
//and of course starts them here...
}
private void Receive()
{
while(true)
{
Heartbeat();
}
}
private void Heartbeat()
{
foreach(netClient in clientsList)
{
if (netClient.DataAvalible)
{
netClient.Recive();
}
if (!netClient.IsBufferEmpty())
{
nextMsg = netClient.NextMessage();
if (nextMsg != null)
NewNetMsg(netClient, nextMsg); //Call the event!
}
}
}
}
How can I make the msgHandler.HandleMsg function run in a separate thread or in the MainThread?
Like this, HandleMsg runs in the receiveMessagesThread.
The code above is pseudocode-ish. If there is anything ambigous please let me know.
There are a lot of different ways to move the HandleMsg call onto a different thread, depending on what your requirements are. The simplest way would be to raise the NewNetMsg event on a different thread using the ThreadPool:
ThreadPool.QueueUserWorkItem(s => NewNetMsg(netClient, nextMsg));
You could also use the Task Parallel Library (TPL). You could also add the event to a ConcurrentQueue that is processed by a dedicated background thread. And there are more options. Without more details it is impossible to give a more specific recommendation.