I want to implement polling approach in c# using design patterns with some generic code with the below scenario.
I have 3 console application names Employee, Orders, Salary and in this from the Employee application I am initiating the Orders and Salary console application , once I will initiate application Orders and Salary console application are long running application which will keep on running and we are updating the local text file with the completion status for each of the application.
From the Employee application I have created a Timers objected and using Elapsed Event for 2 sec to check the file text whether it has status of both the file has been completed or not.
So I want to make the below implementation in more generic way or using some other approach/design patterns so that we can achieve the similar polling concept as I have ore complex situation where I have to use the same repetitive code for each time . Any suggestion on this ?
var poolingTimer = new Timer(2 * 1000);
poolingTimer.AutoReset = false;
poolingTimer.Elapsed += async delegate {
if (logic to check if File text has console application completed status) {
poolingTimer.Stop();
} else {
poolingTimer.Start();
}
};
poolingTimer.Start();
Related
I am trying to develop a simple application that must have GUI components. It will be a service in the taskbar tray but must query the database every few minutes to check for changes, then post to a web server the results. It will run 24/7.
This is my first application, and so have been getting some help along the way from SO. When I first used the FluentScheduler, I had trouble (C# FluentScheduler Job not Repeating) but got it working as a simple proof of concept with a console app.
As I tried taking what I had learned and implementing it with my Windows Forms solution, I couldn't get it working at all because once it ran the Application.Run(ThisForm); command, the scheduler did nothing. Eventually while troubleshooting, I stumbled across this:
https://github.com/fluentscheduler/FluentScheduler/issues/169
I see that you're using the library from something like a Windows Forms/WPF application. Starting threads/tasks from a GUI application is a pain in the ***, maybe that's what's biting you. Fingers crossed to be something else, diving up on STA threads, dispatchers, synchronization contexts and alikes is no fun.
So now I am left wondering what I am supposed to do? Am I supposed to develop the scheduled tasks as a console app leaving an API for a WPF application to communicate with, or am I supposed to work through the pain he is describing and make it work within WPF?
As this is my first C# project, it seems pretty complicated to separate the two components, but am willing to learn if that is the right choice. I am still very early in the project just doing proof of concepts of each needed feature and so can easily switch to WPF, UWP, or whatever else is most appropriate. It will have minimal GUI, just a few forms to fill out username / password type stuff and options to sync.
Even though this FluentScheduler has about a quarter million downloads, maybe there is a better one that doesn't suffer from the same limitations you could recommend.
Based on the earlier post you linked to, I see a few problems with your code:
Your call to JobManager.Initialize is unreachable because it occurs after Application.Run, which blocks until the application shuts down (e.g., when the last window is closed).
The FluentScheduler will schedule your job to run on an arbitrary worker thread, but your action accesses or manipulates UI elements. In both WPF and Windows Forms, you can only touch UI elements from the main thread. If your job needs to touch the UI, it must first marshal itself back onto the UI thread.
The scheduled action in your original post does not make sense:
Action someMethod = new Action(() =>
{
Form1 ThisForm = new Form1();
ThisForm.Text ="HELLO";
});
Specifically, you are creating a new window that is never shown, rather than modifying one that already exists.
Here is a simple example project that you should be able to use as a starting point. It displays the current time, updating once per second. I used WPF, as I haven't used Windows Forms in years, and there's no compelling reason to use it these days.
SchedulerText.xaml:
<Window x:Class="WpfTest.SchedulerTest"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<TextBlock x:Name="_textBlock"
FontSize="18pt"
TextAlignment="Center"
VerticalAlignment="Center" />
</Grid>
</Window>
SchedulerTest.xaml.cs:
using System;
using FluentScheduler;
namespace WpfTest
{
public partial class SchedulerTest
{
public SchedulerTest()
{
InitializeComponent();
JobManager.AddJob(
this.DoScheduledWork,
schedule => schedule.ToRunNow().AndEvery(1).Seconds());
}
private void DoScheduledWork()
{
// Go query your database, or do whatever your main job is.
// You don't want to do this on the UI thread, because it
// will block the thread and prevent user interaction.
DoPrimaryWorkOffUIThread();
// If you need to communicate some sort of result to the user,
// do it on the UI thread.
Dispatcher.Invoke(new Action(ShowResultsOnUIThread));
}
private DateTime _currentResult;
private void DoPrimaryWorkOffUIThread()
{
_currentResult = DateTime.Now;
}
private void ShowResultsOnUIThread()
{
_textBlock.Text = $"{_currentResult:h:mm:ss}";
}
}
}
Note that you don't have to initialize the job in the windows's constructor, but that would be the easiest place to do it.
In our App, We are storing questions with Question's startdate, enddate and resultdate. We need to send notification to app (iPhone and Andorid) once startdate of question is arrives.
Can anybody let me know how can we achieve this?
We don't want to use pull method. like in particular time interval it will check for question startdate and send notification.
I have a URL to send Notification for question. I need to call this URL when question's startdate is arrived.
Thanks.
Take a look at Quartz :
Quartz.NET is a full-featured, open source job scheduling system that can be used from smallest apps to large scale enterprise systems
Quartz Enterprise Scheduler .NET
You can create a new Quarts Job, lets call it QuestionSenderJob. Then your application can schedule a task in Quartz scheduler, jobs can have many instances of same Job with custom data - in your case QuestionId.
Additionally it supports storing Job scheduling in your SQL database (there are DDL Scripts included) so you can create some relations if you need for UI for example.
You can find table-creation SQL scripts in the "database/dbtables" directory of the Quartz.NET distribution
Lesson 9: JobStores
This way you leave firing in right moment to Quartz engine.
When you will go through Quartz .NET basics, see this code snippet I made a for your case to schedule job. Perhaps some modifications will be necessary thought.
IDictionary<string, object> jobData = new Dictionary<string, object> { { "QuestionId", questionId } };
var questionDate = new DateTime(2016, 09, 01);
var questionTriggerName = string.Format("Question{0}_Trigger", questionId);
var questionTrigger = TriggerBuilder.Create()
.WithIdentity(questionTriggerName, "QuestionSendGroup")
.StartAt(questionDate)
.UsingJobData(new Quartz.JobDataMap(jobData))
.Build();
scheduler
.ScheduleJob(questionSenderJob, questionTrigger);
Then in Job you will get your questionId through JobExecutionContext.
public class QuestionSenderJob: IJob
{
public void Execute(JobExecutionContext context)
{
JobDataMap dataMap = context.JobDetail.JobDataMap;
// Extract question Id and send message
}
}
What about using the Task Scheduler Managed Wrapper?
You do not want to use pooling, but if you write your own class that will encapsulate Timer (e.g. System.Thread.Timer) and check for the time each second, that will not take much resources. Depending on how exact you need it, you could check also less often, e.g. each minute. Maybe you should reconsider it.
If you use any third party service to manage your push notification such as Azure Notification Hub, Parse.com, ... they offer an integrated way to schedule push notifications. Either by passing in a send date or let them run a job periodically. I'm a user of the Azure service and it works very well.
The best implementation i can advice right now is for you to send the notification from a server.
All you just need is a good scheduler that can dispatch operation.
For me, my server is powered by Javascript (NodeJS) so i use "node-schedule". All i just do is
var schedule = require('node-schedule');
//Reporting rule at minute 1 every hour
var rule = new schedule.RecurrenceRule();
rule.minute = 1;
schedule.scheduleJob(rule, function () {
console.log(new Date().toTimeString() + ' Testing Scheduler! Executing Every other minute');
//sendPush()
});
What I have is an AJAX form on a View that makes a call to the server. This call perform n number of tasks where n is a number decided by records in a database (typically no more than 10 records). Each record corresponds to a Build Definition in TFS so what I am trying to do is get all of these Build Definitions, queue them in TFS, and as each build completes update the UI so that user knows which builds have completed.
Unfortunately I am not sure about how best to do this. I was thinking something along these lines:
foreach (var dep in builds)
{
TFS tfsServer = new TFS(TFS_SERVER_ADDRESS);
IBuildServer buildServer;
int id = tfsServer.QueuBuild(dep.TeamProject, dep.BuildDefinition);
string teamProject = dep.TeamProject;
Task.Factory.StartNew(() => GetBuildStatus(teamProject, id, tfsServer));
}
The task that is called is:
private void GetBuildStatus(string TeamProject, int BuildID, TFS Server)
{
Server.GetBuildStatus(TeamProject, BuildID);
AsyncManager.OutstandingOperations.Decrement();
}
The problem here is that my Completed method isn't going to get called until all of the builds have completed. How would I go about feeding data back up to the UI a piece at a time?
It is also worth mentioning that the GetBuildStatus method looks like this:
do
{
var build = buildsView.QueuedBuilds.FirstOrDefault(x => x.Id == BuildID);
if(build != null)
{
status = build.Status;
detail = build.Build;
}
} while (status != QueueStatus.Completed);
return detail.Status.ToString();
Given that the duration of a build will be longer than the timeout for an HTTP request you cannot leave the browser waiting while this happens. You need to return a page and then poll for updates from that page using AJAX. Typically you'd have a timer in javascript that triggers a regular call back to the server to get the updated status information.
But, since you are using .NET you could also consider trying SignalR which lets you use long polling, server sent events or web sockets to wait for updates from the server and it wraps it all up in some easy to implement .NET classes and Javascript.
I am trying to design a multithreaded windows application mostly serves for our clients to send emails fastly to their customers(there can be millions as there is a big telecommunication company), and I need design hints.(I am sorry that Q is long)
I fairly read articles about the multithreaded applications. I also read about SmartThread Pool, .NET ThreadPool, Task Parallel Library and other SO questions. But I could not come with a correct design. My logic is like that :
Within start of the program(Email engine), a timer starts and check if there any email campaigns in database(Campaigns table) that has Status 1(new campaign).
If there are, Campaign Subscribers should be queried from DB and should be written to another table(SqlBulkCopy) called SubscriberReports table and update the Campaign's Status to 2 in Campaigns table.
Timer also listens Campaigns with Status 2 to call another method to customize the campaign for each Subscriber, creates a Struct that has customized properties of the Subscriber.
Thirdly a SendEmail method is invoked to send the email via SMTP. What I tried so far is below(I know that ThreadPool is wrong here, and I have bunch of other mistakes). Can you pls suggest and help me how to design such an application. Highly appreciate any help. Thanks alot for your time.
private void ProcessTimer(object Source, ElapsedEventArgs e)
{
Campaigns campaign = new Campaigns();
IEnumerable<Campaigns> campaignsListStatusOne = // Get Campaign Properties to a List
IEnumerable<Campaigns> campaignsListStatusTwo = // Get Campaign Properties to a List
foreach (Campaigns _campaign in campaignsListStatusOne)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(CheckNewCampaign), _campaign.CampaignID);
}
foreach (Campaigns _campaign in campaignsListStatusTwo)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(CustomizeMail), _campaign.CampaignID);
}
}
private void CheckNewCampaign(object state)
{
int campaignID = (int)state;
DataTable dtCampaignSubscribers = // get subscribers based on Campaign ID
campaign.UpdateStatus(campaignID, 2);
}
private void CustomizeMail(object state)
{
int campaignID = (int)state;
CampaignCustomazition campaignCustomizer;
IEnumerable<SubscriberReports> reportList = // get subscribers to be sent from Reports table
foreach (SubscriberReports report in reportList)
{ // 3 database related methods are here
campaignCustomizer = new CampaignCustomazition(report.CampaignID, report.SubscriberID);
campaignCustomizer.CustomizeSource(report.CampaignID, report.SubscriberID, out campaignCustomizer.source, out campaignCustomizer.format);
campaignCustomizer.CustomizeCampaignDetails(report.CampaignID, report.SubscriberID, out campaignCustomizer.subject, out campaignCustomizer.fromName, out campaignCustomizer.fromEmail, out campaignCustomizer.replyEmail);
campaignCustomizer.CustomizeSubscriberDetails(report.SubscriberID, out campaignCustomizer.email, out campaignCustomizer.fullName);
ThreadPool.QueueUserWorkItem(new WaitCallback(SendMail), campaignCustomizer);
}
}
private void SendMail(object state)
{
CampaignCustomazition campaignCustomizer = new CampaignCustomazition();
campaignCustomizer = (CampaignCustomazition)state;
//send email based on info at campaignCustomizer via SMTP and update DB record if it is success.
}
There is little to be gained here by using threading. What threads buy you is more cpu cycles. Assuming you have a machine with multiple cores, pretty standard these days. But that's not what you need to get the job done quicker. You need more dbase and email servers. Surely you only have one of each. Your program will burn very little core, it is constantly waiting for the dbase query and the email server to complete their job.
The only way to get ahead is to overlap the delays of each. One thread could constantly be waiting for the dbase engine, the other could be constantly waiting for the email server. Which is better than one thread waiting for both.
That's not likely to buy you much either though, there's a big mismatch between the two. The dbase engine can give you thousands of email addresses in a second, the email server can only a few hundred emails in a second. Everything is throttled by how fast the email server works.
Given the low odds of getting ahead, I'd recommend you don't try to get yourself into trouble with threading at all. It has a knack for producing very hard to diagnose failure if you don't lock properly. The amount of time you can spend on troubleshooting this can greatly exceed the operational gains from moving a wee bit faster.
If you are contemplating threading to avoid freezing a user interface then that's a reasonable use for threading. Use BackgroundWorker. The MSDN Library has excellent help for it.
Need to develop a Webserver Monitoring system. There may be Hundreds of webserver running on different servers. This system need to keep monitoring of each webservice at a given interva and update the status in DB.
The current options designed.
Options1: Created class Monitorig it has Method1 which call the webservice dynamically on regular interval say 10 Min. And stores the status(Fail/Success) data to DB.
In a for loop I'm creating a new instance of monitoring class every time and a new Thread.
Example.
foreach(int i in idlist)
{
Monitoring monObj = new Monitoring();
Thread workerT = new Thread(monObj.MonitorWebService);
workerT.Start(i);
}
in the MonitorWebService API there is a infinity for loop
which does calling of the given webservice at a given interval as 1 min or 10 min etc. To process this in a regular inverval I'm using EventWaitHandle.WaitOne(T1 * 1000, false) instead of Thread.Sleep(). Here T1 can be 1 min or 1 or 5 hours.
Oprion 2:
in the for loop open a new appdomain with new Name and open a new thread as given below.
foreach(int i in idlist)
{
string appDNname = WSMonitor + i.ToString();
AppDomain WMSObj = AppDomain.CreateDomain(appDNname);
Type t= typeof(Monitoring);
Monitoring monWSObj = (Monitoring) WMSObj.CreateInstanceAndUnwrap(Assembly.GetExecuti ngAssembly().FullName, t.FullName);
Thread WorkerT = new Thread(monWSObj.MonitorWebService);
WorkerT.Start(i);
}
in option2 I'm unloading the AppDomain when the time interval is more then 10 min. And when ever its required loading. I thought option 2 will release resource when its not required and reload when its required.
Which is the best/better approach? Do we have any better solution. A Quick Help is highly appreciated.
First of all:
Option 2 is bad. It will not unload any more data than your Option 1 does.
.Net will automatically unload all application data when it is no longer referenced/needed. It just won't unload the application itself. But in your case you cannot unload your application itself anyways so using an AppDomain is completely useless here.
Option 1 is not terribly good either because (abusing) Threadsyncs for timining has huge overhead and is never a good idea.
Better options are:
1) If you don't need to run permanently just have the external windows task scheduler call your application at the needed times. This has the advantage that it is easily externally configurable and you don't have to worry about any timing in your code at all.
2) If you need/want to run permanently then the most simple and clear way would be to use one of the available Timer objects.
3) If you don't like 2) use a loop with Thread.Sleep (Don't try to abuse the Sleep interval for timing, just sleep e.g. 1 min and then wake up and check if things need to be done).