There is an application that collects news from rss of news agencies maybe like Google Reader!.
I want to call a method to update my links in DB in a period of the time and it continues to the Application life time.
something like a clock !!!
without any pause
I know some info about Threading
but the problem is :
Where can I call my Update method?
I have some classes that some of them derive from others and I use to layer in my Project
I call the method in Global.asax:
protected void Application_Start(object sender, EventArgs e)
{
Thread thread = new Thread(new ThreadStart(UpdateRss));
thread.Start();
Thread.Sleep(1000);
}
public void UpdateRss()
{
while (true)
{
using (LinkService linkSrv = new LinkService())
{
linkSrv.UpdateLinksFromRSS();
}
}
}
and the definition of UpdateLinksFromRSS in LinkService is:
public void UpdateLinksFromRSS()
{
List<RssInfo> q;
using (RssService RssSrv = new RssService())
{
q = RssSrv.GetRssInfoes();
}
foreach (var item in q)
{
AddLink(item);
}
}
Honestly the problem is i have a property in BaseService that is defined like this:
public static System.Web.Caching.Cache Cache
{
get { return HttpContext.Current.Cache; }
}
when I run the project!
I got an error from this line: return HttpContext.Current.Cache;
Related
I have a strange problem with following code, that is started about every minute.
Normally everything works fine, but sometimes the HandleCalcStatistikMarkersDone function raises an error because of a NullReferenceException.
I try to explain with the code:
I have a class Strategies. This class is started about every minute to calculate and update some information in a MySQL database. This class is instantiated multiple times in separate threads within a ticker on a form.
public partial class mainForm: Form
{
//do something including ticker, that starts RunStatistik about every minute after the previous thread ended
private void RunStatistik()
{
foreach (InternalObject objPar in InternalObjects)
{
Strategies.StrategyParameter giveParms = new Strategies.StrategyParameter();
giveParms.pair= objPar.pair;
Strategies strat = new Strategies();
Thread calcStatistikThread = new Thread(new ParameterizedThreadStart(strat.CalcCoinStatistik));
calcStatistikThread.Start(giveParms);
}
}
}
Internally in the upper initiated Strategies thread, there are stared some additional threads.
Those threads have a "DoneEvent" which is raised at the end of the function.
To notice, that all threads have ended before the main thread ends, I collect all subthreads in a List CalcStatistikMarkersThreads and wait until the list is empty.
The subthreads should remove themselves out of the upper List via the ThreadDone event.
But sometimes the searched thread (CalcStatistikMarkersThreads.Find) is not found anymore and I get a NullReferenceException.
The question is why?!
Could you tell me, why? And possibly how to prevent?
Thanks in advance.
class Strategies
{ public event EventHandler ThreadDone;
private List<Thread> CalcStatistikMarkersThreads;
//do something
public void CalcCoinStatistik(object parameters)
{
StrategyParameter givenParms = (StrategyParameter)parameters;
Pair internalPair = givenParms.pair
//do something
if (CalcStatistikMarkersThreads == null)
{
CalcStatistikMarkersThreads = new List<Thread>();
}
foreach (InternalTodo in InternalToDos)
{
Strategies strat = new Strategies();
CalcStatistikMarkersParameter csp = new CalcStatistikMarkersParameter();
csp.parm1 = param;
strat.ThreadDone += HandleCalcStatistikMarkersDone;
Thread candleCalc = new Thread(new ParameterizedThreadStart(strat.CalcStatistikMarkers));
CalcStatistikMarkersThreads.Add(candleCalc);
candleCalc.Start(csp);
while (CalcStatistikMarkersThreads.Count != 0)
{
Task.Delay(1000).Wait();
}
}
}
public void CalcStatistikMarkers(object parm)
{
//do something
if (ThreadDone != null)
ThreadDone(this, new ThreadInfoEventArgs(Thread.CurrentThread.ManagedThreadId));
}
public void HandleCalcStatistikMarkersDone(object sender, EventArgs e)
{
Guid workGUID = Guid.NewGuid();
ThreadInfoEventArgs tEv = (ThreadInfoEventArgs)e;
Thread currentThread;
try
{
currentThread = CalcStatistikMarkersThreads.Find(xy => xy.ManagedThreadId == tEv.ThreadID);
//HERE THE NullReferenceException is raised sometimes
CalcStatistikMarkersThreads.Remove(currentThread);
}
catch (Exception ex)
{
throw ex;
}
}
public class ThreadInfoEventArgs : EventArgs
{
private int threadID;
public ThreadInfoEventArgs(int trID)
{
this.threadID = trID;
}
public int ThreadID
{
get { return threadID; }
}
}
}
Cheers
Air
To clean up code that will use BackgroundWorker often and with the same settings, I created the following class as a helper:
public class MyBackGroundWorker : System.ComponentModel.BackgroundWorker
{
private Action _action;
private Action _stopAction;
public List<dynamic> Parameters { get; set; } = new List<dynamic>();
MyBackGroundWorker(Action method, Action doWhenFinished = null)
{
this._action = method;
this._stopAction = doWhenFinished;
Init();
}`
"Init()" contains all of the settings that will be applied each time:
private void Init()
{
this.WorkerReportsProgress = true;
this.WorkerSupportsCancellation = true;
this.DoWork += new DoWorkEventHandler(StartWork);
this.RunWorkerCompleted += new RunWorkerCompletedEventHandler(WorkDone);
}
And the handlers and public methods are:
private void StartWork(object sender, DoWorkEventArgs e)
{
if (Parameters.Count() > 0)
{
ParameterInfo[] pi = _action.Method.GetParameters();
//now i'm stuck!!!!!
}
else
{
_action.Method.Invoke(null, this.Parameters);
//i know this is wrong, wrote it in to illustrate the goal
}
}
private void WorkDone(object sender, RunWorkerCompletedEventArgs e)
{
_stopAction.Method.Invoke(null, null); //>.<
}
public void Go()
{
RunWorkerAsync();
}
public void Stop()
{
this.CancelAsync();
}
Obviously there are some problems here. The end goal is to initialize the object with a method to start running, a method to do at the end (optional), and a parameter collection one adds to before running. A calling class might have a section like this:
using(var cmd = new MyBackGroundWorker(method1, StopLoadingSpinner))
{
cmd.Parameters.Add("Stringparam");
cmd.Parameters.Add(1);
StartLoadingSpinner();
cmd.Go();
}
I've looked some things up involving delegates to try to sort this out, but I know that's only one piece of the puzzle. From there, my searches online have been fruitless, as I'm not sure in what direction I need to research. Where do I go from here? The idea itself may be fundamentally flawed, and I'm willing to accept that, but what can I do to accomplish my goal of a BackgroundWorker so simply used by the calling method, while using variable types and counts of parameters based on the method I'm trying to run in the background?
I'm a little bit confused about how this should work. I have multiple objects saved in a XML file and those objects have a property for TimeBetweenReposts (like 10 minutes) and TimesToRepost (like 20 times).
Each object in part should trigger a function every TimeBetweenReposts minutes.
How can I do this?
You have a few options, your most simple would be to create a separate thread which runs a function that looks something like this:
private void CheckTime()
{
while (!exitCondition) //So you can cleanly kill the thread before exiting the program.
{
if (nextCheck < DateTime.Now)
{
DoAction();
nextCheck = DateTime.Now + TimeBetweenReposts;
}
Thread.Sleep(1000); //Can be tweaked depending on how close to your time it has to be.
}
}
Otherwise you could make entries in the system task scheduler.
You can use a Timer to do something every X seconds, or minutes or whatever you need.
You can implement a Timer like this :
public class XMLFilesManager
{
Timer tm = null;
public XMLFilesManager()
{
this.tm.Elapsed += new ElapsedEventHandler(XMLFilesManagerTimer_Elapsed);
this.tm.AutoReset = true;
this.tm = new Timer(60000);
}
public void Start()
{
this.tm.Start();
}
public void Stop()
{
this.tm.Stop();
}
protected void XMLFilesManagerTimer_Elapsed(object sender, ElapsedEventArgs e)
{
this.tm.Stop();
try
{
Execute();
}
catch (Exception ex)
{
// LOG ERROR
}
finally
{
this.tm.Start();
}
}
private void Execute()
{
// PUT YOUR BUSINESS LOGIC HERE
}
}
Then, you can add a property to store the history of your execution, like :
// History of your object executions : object's identifier, last execution time and nb times you have execute the function for this object
List<Tuple<int,DateTime,int>> objectExecutionHistory = null;
And in the execute function, loop on your xml objects, and do what you have to do.
I'm working on a class that looks like this:
public class MatchmakingService {
private bool working;
private List<MatchmakingUser> matchmakingUsers;
// ...
public MatchmakingService()
{
matchmakingUsers = new List<MatchmakingUser>();
}
public void StartService () {
var thread = new Thread(this.MatchmakingWork);
working = true;
thread.Start();
}
void MatchmakingWork () {
while (working)
{
// some work
Thread.Sleep(1000);
}
}
// ...
public void AddMatchmakingUser(MatchmakingUser user)
{
matchmakingUsers.Add(user);
}
}
Now I'm worried about matchmakingUsers list so I figured I'd just call this AddMatchmakingUser to execute in this service thread, but don't really know how to. I've read about Dispatcher class but either mono in Unity doesn't have it or it's a different technology entirely. Basically I'd like to do:
MatchmakingService mmService = new MatchmakingService();
mmService.Start();
// sometime later when needed
mmService.Somehowinvokeinworkingthread(mmService.AddMatchMakingUser(...));
Just call AddMatchmakingUser from any thread and synchronize all the code that's accesing the list to prevent them from occuring at the same time and causing a race condition:
public void AddMatchmakingUser(MatchmakingUser user)
{
lock (matchmakingUsers)
{
matchmakingUsers.Add(user);
}
}
Do the same inside MatchmakingWork whenever you are accessing the list.
First of all, I'm Java programmer and I'm new on C# and I need opinion of C# developers. I'm developing an application that connecting to database (firebird 1.5), query some data and return to me so there's nothing to be complicated but unfortunately I've stuck in some things :
As we know the database connection should be realised in separate thread cause it's a highweight operation and all the connections should be in connection pool in order to reuse already opened connection instead create the new one.
So here go my first question - how to organize connection pool properly?
(What about connection pool I've read that usually connection pool is already realised by data providers and I can just set it in connection parametres someway like "connectionBuilder.Pooling = true;")
What about queries? I mean that I've always use a Query per-Thread (and I think that is right cause we also do a highweight operation, am I wrong? Anyway I'd glad to see your best practices with organizing database work) and in Java I just do return Query result from separate thread by use an interfaces and anonymous classes like this:
In DBHelper.class (DBHelper is a singleton)
public interface QueryListener {
public void onSuccess(ArrayList<?>);
public void onError(Exception e);
}
public synchronized void getPromoActions(final QueryListener listener) {
if (listener != null) {
try {
ArrayList<String> myPromoActions;
.............
// some query's code
.....
listener.onSucces(myPromoActions);
} catch(Exception e) {
listener.onError(e);
} finally {
closeDatabase();
}
}
}
in some UI-class (for eaxample MainWindow)
public void getPromoActions(){
new Thread(new Runnable() {
#Override
public void run() {
DBHelper.getInstance().getPromoActions(new QueryListener() {
#Override
public void onSuccess(ArrayList<?>) {
// set Data to UI element such as Table
}
#Override
public void onError(Exception e){
// Handling exception
}
});
}
}).start();
}
In C# I should use delegates to mark which method will execute in thread, but unfortionally I can't send any callback as parameter - so how I should return my Query results to main UI thread?
UPD
I've understand a little bit how to work with delegates and events but have a problem with raising a custom event. I had declared an EventHandler and an custom EventArgs:
public delegate void QueryResultEventHandler(object sender, QueryResultEventArgs e);
public class QueryResultEventArgs : EventArgs
{
public List<String> QueryResult { get; set; }
public int QueryRecordsCount { get; set; }
}
And in My DBHelper.class I declared a next field and event:
private QueryResultEventHandler _queryResult;
public event QueryResultEventHandler onQueryResult
{
add
{
lock (this)
{
_queryResult += value;
}
}
remove
{
lock (this)
{
_queryResult -= value;
}
}
}
In UI class (MainWindow) I use next code:
public void GetAllDistricts() {
DBHelper.Instance.onQueryResult += new QueryResultEventHandler(GetAllDistricsResultHandler);
DBHelper.Instance.GetAllDistricts();
}
public void GetAllDistricsResultHandler(object sender, QueryResultEventArgs e){
// Here I'm adding the query result to Table
}
So my problem now is a how to raise an event asynchronously? In my DBHelper.class I'm trying to use beginInvoke&endInvoke with _query delegate but it seems that I had missed some code lines whatever it was I can't understand what I'm doing wrong an how to raise event asynchronously? Here my DBHelper.class code:
public void GetAllDistricts() {
try
{
if (_queryResult != null)
{
//** This code should run asynchronously ---------->
using (FbConnection connection = GetConnection())
{
FbCommand getAllDistrictsCommand = new FbCommand();
getAllDistrictsCommand.CommandText = "SELECT * FROM SEND";
getAllDistrictsCommand.Connection = connection;
QueryResultEventArgs args = new QueryResultEventArgs();
using (FbDataReader reader = getAllDistrictsCommand.ExecuteReader())
{
while (reader.Read())
{
//Here must be the processing of query results and filling the
//QueryResultEventArgs
args.QueryResult.Add(reader[0].ToString());
}
args.QueryRecordsCount = reader.GetInt32(reader.GetOrdinal("Rows"));
// And here after sucessfull query I should call OnQueryResult()
OnQueryResult(args);
}
}
//**<--------------------
}
else
{
throw new Exception("...Some exception message...");
}
}
catch (Exception e)
{
log.ErrorException(e.Message, e);
throw new Exception("...Some exception message...");;
}
finally {
CloseConnection();
}
}
// The QueryResultEvent method
protected void OnQueryResult(QueryResultEventArgs e)
{
if (_queryResult != null)
{
_queryResult(this, e);
}
}
First about connection pooling. If you will use ADO.NET then you do not need to worry about that, because it's already there. You don't need to do any extra work, you just create a connection:
using (var connection = new SqlConnection(connectionString))
{
// Queries to DB
}
You should always Close or Dispose you connections. The names of the methods look "scary" but actually connections are reused. Please read this MSDN article to get more details.
The code you proposed looks over-complicated. I think you should consider using async/await pattern which is in general not multithreaded, but it handles UI responsiveness issues and simplifies writing/reading of the code. In newer versions of .NET almost all methods that are potentially long to execute has async versions. So for example your data access layer might look like that (I'm using Dapper ORM's QueryAsync method just to keep code short and simple):
public async Task<IList<District>> GetAllDistrictsAsync()
{
using (var connection = await GetConnectionAsync())
{
return (await connection.QueryAsync<District>("select * from Districts")).ToList();
}
}
public async Task<IDbConnection> GetConnectionAsync()
{
var connectionString =
ConfigurationManager.ConnectionStrings["DbConnectionString"].ConnectionString;
var connection = new SqlConnection(connectionString);
await connection.OpenAsync();
return connection;
}
And then somewhere on UI:
private async void Button_Click(object sender, EventArgs e)
{
var districts = await GetAllDistrictsAsync();
}
If you still need to execute some code in different thread you should look at Tasks namespace.
Task.Factory
.StartNew<IList<District>>(GetAllDistricts)
.ContinueWith(districts =>
{
// UI thread
}, TaskScheduler.FromCurrentSynchronizationContext());
In this example GetAllDistricts is not async and is executed in different thread. But ContinueWith will be executed in UI thread because of TaskScheduler.FromCurrentSynchronizationContext().
public void GetAllDistricts() {
DBHelper.Instance.onQueryResult +=
new QueryResultEventHandler(GetAllDistricsResultHandler);
new Thread(
new ThreadStart(DBHelper.Instance.GetAllDistricts)
).Start();
}
But the problem you will face is that you won't be able to access your UI controls from the EventHandler as it will be denied because you are not in the same thread anymore...
Refer to that article for some explanation
How to update the GUI from another thread in C#?
To avoid this you can maybe use the BackgroundWorker control.
Use this option
http://www.asp.net/mvc/overview/older-versions-1/models-(data)/creating-model-classes-with-the-entity-framework-cs
it is easy to use and easy to database operation with less code.