///<summary>Wrapper method to call the passed-in func in a seperate thread connected to the reporting server. ///This method should only be used for SELECT, with the exception DashboardAR. Using this for create/update/delete may cause duplicates. ///The return type of this function is whatever the return type of the method you passed in is. ///Throws an exception if anything went wrong executing func within the thread.</summary> ///<param name="doRunOnReportServer">If this false, the func will run against the currently connected server.</param> public static T RunFuncOnReportServer <T>(Func <T> func, bool doRunOnReportServer = true) { if (!doRunOnReportServer) { return(func()); } Exception ex = null; ODThread threadGetTable = new ODThread(new ODThread.WorkerDelegate((ODThread o) => { DataAction.Run(() => { o.Tag = func(); } //set the tag to the func's output. , ConnectionNames.DentalOfficeReportServer); //run on the report server. if not set up, automatically runs on the current server. })); threadGetTable.AddExceptionHandler(new ODThread.ExceptionDelegate((Exception e) => { ex = e; })); threadGetTable.Name = "ReportComplexGetTableThread"; threadGetTable.Start(true); threadGetTable.Join(Timeout.Infinite); //Now that we are back on the main thread, it is now safe to throw exceptions. if (ex != null) { ExceptionDispatchInfo.Capture(ex.InnerException ?? ex).Throw(); //This preserves the stack trace of the InnerException. } return((T)threadGetTable.Tag); }
private void StartRefreshThread(Func <UserControlDashboardWidget, bool> funcData, string name) { ODThread previousThread = null; if (_threadRefresh != null && !_threadRefresh.HasQuit) { previousThread = _threadRefresh; } _threadRefresh = new ODThread((o) => { if (previousThread != null) { //Allow the previous thread to finish updating its data, but quit before updating UI if it hasn't started yet. previousThread.QuitSync(Timeout.Infinite); } foreach (UserControlDashboardWidget widget in ListOpenWidgets) { if (funcData(widget)) { if (widget.IsDisposed || !widget.IsHandleCreated) { continue; } if (!o.HasQuit) { widget.RefreshView(); //Invokes back to UI thread for UI update. } } } }); _threadRefresh.Name = name; _threadRefresh.AddExceptionHandler(ex => ex.DoNothing()); //Don't crash program on Dashboard data fetching failure. _threadRefresh.Start(); }
private void FormJobNew_Load(object sender, EventArgs e) { textSearch.Text = InitialSearchString; listBoxUsers.Items.Add("Any"); _listUsers = Userods.GetDeepCopy(true); _listUsers.ForEach(x => listBoxUsers.Items.Add(x.UserName)); //Statuses listBoxStatus.Items.Add("Any"); _listJobStatuses = Enum.GetValues(typeof(JobPhase)).Cast <JobPhase>().ToList(); _listJobStatuses.ForEach(x => listBoxStatus.Items.Add(x.ToString())); //Categories listBoxCategory.Items.Add("Any"); _listJobCategory = Enum.GetValues(typeof(JobCategory)).Cast <JobCategory>().ToList(); _listJobCategory.ForEach(x => listBoxCategory.Items.Add(x.ToString())); ODThread thread = new ODThread((o) => { //We can reduce these calls to DB by passing in more data from calling class. if available. if (_listJobsAll == null) { _listJobsAll = Jobs.GetAll(); Jobs.FillInMemoryLists(_listJobsAll); } try { _listFeatureRequestsAll = FeatureRequests.GetAll(); } catch (Exception ex) { ex.DoNothing(); _listFeatureRequestsAll = new List <FeatureRequest>(); } _listBugsAll = Bugs.GetAll(); this.Invoke((Action)ReadyForSearch); }); thread.AddExceptionHandler((ex) => { /*todo*/ }); thread.Start(); }
///<summary>Can return null if the thread fails to join.</summary> public static List <Bug> GetAll() { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { return(Meth.GetObject <List <Bug> >(MethodBase.GetCurrentMethod())); } //Create an ODThread so that we can safely change the database connection settings without affecting the calling method's connection. ODThread odThread = new ODThread(new ODThread.WorkerDelegate((ODThread o) => { //Always set the thread static database connection variables to set the serviceshq db conn. #if DEBUG new DataConnection().SetDbT("localhost", "bugs", "root", "", "", "", DatabaseType.MySql, true); #else new DataConnection().SetDbT("server", "bugs", "root", "", "", "", DatabaseType.MySql, true); #endif string command = "SELECT * FROM bug ORDER BY CreationDate DESC"; o.Tag = Crud.BugCrud.TableToList(DataCore.GetTable(command)); })); odThread.AddExceptionHandler(new ODThread.ExceptionDelegate((Exception e) => { })); //Do nothing odThread.Name = "bugsGetAllThread"; odThread.Start(true); if (!odThread.Join(THREAD_TIMEOUT)) { return(null); } return((List <Bug>)odThread.Tag); }
///<summary></summary> private string RunWebMethod(Func <string> funcWebMethod) { Exception ex = null; RemotingRole remotingRoleCur = RemotingClient.RemotingRole; //Create an ODThread so that we can safely change the database connection settings without affecting the calling method's connection. ODThread odThread = new ODThread(new ODThread.WorkerDelegate((ODThread o) => { //Change the remoting role to ServerWeb (this will get set back to remotingRoleCur later. RemotingClient.RemotingRole = RemotingRole.ServerWeb; //Set new database connection settings if designated. E.g. some unit tests need to set and utilize userLow and passLow. if (!string.IsNullOrEmpty(_server) && !string.IsNullOrEmpty(_db) && !string.IsNullOrEmpty(_user)) { new DataConnection().SetDbT(_server, _db, _user, _password, _userLow, _passLow, DatabaseType.MySql); } //Execute the func that was passed in now that our remoting role and database connection are correct. o.Tag = funcWebMethod(); })); odThread.AddExceptionHandler(new ODThread.ExceptionDelegate((Exception e) => { ex = e; //Cannot throw exception here due to still being in a threaded context. })); if (ex != null) { throw ex; //Should never happen because this would be a "web exception" as in the ProcessRequest could not even invoke or something like that. } odThread.Name = "threadMiddleTierUnitTestRunWebMethod"; //Set the remoting role back after exiting the thread. odThread.AddExitHandler((e) => RemotingClient.RemotingRole = remotingRoleCur); odThread.Start(true); odThread.Join(System.Threading.Timeout.Infinite); return((string)odThread.Tag); }
///<Summary>Will not mark completed feature requests as approved.</Summary> public static void MarkAsApproved(List <long> listRequestIDs) { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { Meth.GetVoid(MethodBase.GetCurrentMethod(), listRequestIDs); return; } //Create an ODThread so that we can safely change the database connection settings without affecting the calling method's connection. ODThread odThread = new ODThread(new ODThread.WorkerDelegate((ODThread o) => { //Always set the thread static database connection variables to set the serviceshq db conn. #if DEBUG new DataConnection().SetDbT("localhost", "bugs", "root", "", "", "", DatabaseType.MySql, true); #else new DataConnection().SetDbT("server", "bugs", "root", "", "", "", DatabaseType.MySql, true); #endif string command = "UPDATE request SET Approval=7 " //Approved + "WHERE Approval!=9 " //9=Complete + "AND RequestId IN (" + String.Join(",", listRequestIDs) + ")"; o.Tag = Db.NonQ(command); })); odThread.AddExceptionHandler(new ODThread.ExceptionDelegate((Exception e) => { })); //Do nothing odThread.Name = "featureMarkAsInProgressThread"; odThread.Start(true); if (!odThread.Join(2000)) //Give this thread up to 2 seconds to complete. { return; } }
///<Summary>Gets name from database. Not very efficient.</Summary> public static string GetSubmitterName(long submitter) { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { return(Meth.GetString(MethodBase.GetCurrentMethod(), submitter)); } //Create an ODThread so that we can safely change the database connection settings without affecting the calling method's connection. ODThread odThread = new ODThread(new ODThread.WorkerDelegate((ODThread o) => { //Always set the thread static database connection variables to set the serviceshq db conn. #if DEBUG new DataConnection().SetDbT("localhost", "bugs", "root", "", "", "", DatabaseType.MySql, true); #else new DataConnection().SetDbT("server", "bugs", "root", "", "", "", DatabaseType.MySql, true); #endif string command = "SELECT UserName FROM buguser WHERE BugUserId=" + submitter; o.Tag = Db.GetScalar(command); })); odThread.AddExceptionHandler(new ODThread.ExceptionDelegate((Exception e) => { })); //Do nothing odThread.Name = "bugsGetSubmitterNameThread"; odThread.Start(true); if (!odThread.Join(THREAD_TIMEOUT)) { return(""); } return(odThread.Tag.ToString()); }
///<summary>Gets one Bug from the db. Can return null if the thread fails to join.</summary> public static Bug GetOne(long bugId) { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { return(Meth.GetObject <Bug>(MethodBase.GetCurrentMethod(), bugId)); } //Create an ODThread so that we can safely change the database connection settings without affecting the calling method's connection. ODThread odThread = new ODThread(new ODThread.WorkerDelegate((ODThread o) => { //Always set the thread static database connection variables to set the serviceshq db conn. #if DEBUG new DataConnection().SetDbT("localhost", "bugs", "root", "", "", "", DatabaseType.MySql, true); #else new DataConnection().SetDbT("server", "bugs", "root", "", "", "", DatabaseType.MySql, true); #endif o.Tag = Crud.BugCrud.SelectOne(bugId); })); odThread.AddExceptionHandler(new ODThread.ExceptionDelegate((Exception e) => { })); //Do nothing odThread.Name = "bugsGetOneThread"; odThread.Start(true); if (!odThread.Join(THREAD_TIMEOUT)) { return(null); } return((Bug)odThread.Tag); }
///<Summary>Checks bugIDs in list for incompletes. Returns false if incomplete exists.</Summary> public static bool CheckForCompletion(List <long> listBugIDs) { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { return(Meth.GetBool(MethodBase.GetCurrentMethod(), listBugIDs)); } //Create an ODThread so that we can safely change the database connection settings without affecting the calling method's connection. ODThread odThread = new ODThread(new ODThread.WorkerDelegate((ODThread o) => { //Always set the thread static database connection variables to set the serviceshq db conn. #if DEBUG new DataConnection().SetDbT("localhost", "bugs", "root", "", "", "", DatabaseType.MySql, true); #else new DataConnection().SetDbT("server", "bugs", "root", "", "", "", DatabaseType.MySql, true); #endif string command = "SELECT COUNT(*) FROM bug " + "WHERE VersionsFixed='' " + "AND BugId IN (" + String.Join(",", listBugIDs) + ")"; o.Tag = Db.GetCount(command); })); odThread.AddExceptionHandler(new ODThread.ExceptionDelegate((Exception e) => { })); //Do nothing odThread.Name = "bugsCheckForCompletionThread"; odThread.Start(true); if (!odThread.Join(THREAD_TIMEOUT)) { return(true); } if (PIn.Int(odThread.Tag.ToString()) != 0) { return(false); } return(true); }
///<summary>Must pass in version as "Maj" or "Maj.Min" or "Maj.Min.Rev". Uses like operator. Can return null if the thread fails to join.</summary> public static List <Bug> GetByVersion(string versionMajMin, string filter = "") { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { return(Meth.GetObject <List <Bug> >(MethodBase.GetCurrentMethod(), versionMajMin, filter)); } //Create an ODThread so that we can safely change the database connection settings without affecting the calling method's connection. ODThread odThread = new ODThread(new ODThread.WorkerDelegate((ODThread o) => { //Always set the thread static database connection variables to set the serviceshq db conn. #if DEBUG new DataConnection().SetDbT("localhost", "bugs", "root", "", "", "", DatabaseType.MySql, true); #else new DataConnection().SetDbT("server", "bugs", "root", "", "", "", DatabaseType.MySql, true); #endif string command = "SELECT * FROM bug WHERE (VersionsFound LIKE '" + POut.String(versionMajMin) + "%' OR VersionsFound LIKE '%;" + POut.String(versionMajMin) + "%' OR " + "VersionsFixed LIKE '" + POut.String(versionMajMin) + "%' OR VersionsFixed LIKE '%;" + POut.String(versionMajMin) + "%') "; if (filter != "") { command += "AND Description LIKE '%" + POut.String(filter) + "%'"; } o.Tag = Crud.BugCrud.SelectMany(command); })); odThread.AddExceptionHandler(new ODThread.ExceptionDelegate((Exception e) => { })); //Do nothing odThread.Name = "bugsGetByVersionThread"; odThread.Start(true); if (!odThread.Join(THREAD_TIMEOUT)) { return(null); } return((List <Bug>)odThread.Tag); }
///<summary>NOT Oracle compatible. This will take a set of rows from the specified table from the current database and insert them into a ///different database. It does NOT create tables nor databases if they don't exist, such things need to already exist. Enter text for the ///"whereClause" parameter to filter what rows to retrieve. Needs to include the "WHERE" statement, if it's being used. (Ex. "WHERE PatNum != 2") ///IMPORTANT NOTE -------------- MAKE SURE YOU SET CLASS-WIDE VARIABLES PRIOR TO RUNNING TABLE COMMANDS. - TableName, TablePriKey at the very least.</summary> public static void InsertIntoLargeTable(string whereClause) { #if DEBUG Stopwatch s = new Stopwatch(); s.Start(); #endif SetListPriKeyMaxPerBatch(whereClause); _tempTableName = _tableName; //Set these to be equal for the Insert function - We aren't renaming tables, we are copying from one to another. ODThread odThreadQueueData = new ODThread(QueueBatches); try { lock (_lockObjQueueBatchQueries) { _queueBatchQueries = new Queue <BatchQueries>(); } _areQueueBatchThreadsDone = false; odThreadQueueData.Name = "QueueDataThread"; odThreadQueueData.AddExceptionHandler(new ODThread.ExceptionDelegate((Exception ex) => { _areQueueBatchThreadsDone = true; })); odThreadQueueData.Start(true); InsertBatches(); } catch (Exception ex) { ex.DoNothing(); throw; } finally { odThreadQueueData?.QuitAsync(); _areQueueBatchThreadsDone = true; #if DEBUG s.Stop(); Console.WriteLine("Total time to insert into table " + _tableName + " with " + string.Format("{0:#,##0.##}", _totalRowCount) + " rows: " + (s.Elapsed.Hours > 0?(s.Elapsed.Hours + " hours "):"") + (s.Elapsed.Minutes > 0?(s.Elapsed.Minutes + " min "):"") + (s.Elapsed.TotalSeconds - (s.Elapsed.Hours * 60 * 60) - (s.Elapsed.Minutes * 60)) + " sec"); #endif } }
///<Summary></Summary> public static void CompleteRequests(List <long> listRequestIDs, string versionText) { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { Meth.GetVoid(MethodBase.GetCurrentMethod(), listRequestIDs, versionText); } //Create an ODThread so that we can safely change the database connection settings without affecting the calling method's connection. ODThread odThread = new ODThread(new ODThread.WorkerDelegate((ODThread o) => { //Always set the thread static database connection variables to set the serviceshq db conn. #if DEBUG new DataConnection().SetDbT("localhost", "bugs", "root", "", "", "", DatabaseType.MySql, true); #else new DataConnection().SetDbT("server", "bugs", "root", "", "", "", DatabaseType.MySql, true); #endif string versionString = "\r\n\r\nCompleted in version " + versionText; string command = "UPDATE request SET Approval=9, " //Complete + "Detail=CONCAT( Detail , '" + versionString + "' ) " + "WHERE RequestId IN (" + String.Join(",", listRequestIDs) + ")"; o.Tag = Db.NonQ(command); })); odThread.AddExceptionHandler(new ODThread.ExceptionDelegate((Exception e) => { })); //Do nothing odThread.Name = "featureCheckForCompletionThread"; odThread.Start(true); if (!odThread.Join(2000)) //Give this thread up to 2 seconds to complete. { return; } }
private void FillGridWebSchedTimeSlotsThreaded() { if (this.InvokeRequired) { this.BeginInvoke((Action) delegate() { FillGridWebSchedTimeSlotsThreaded(); }); return; } //Validate time slot settings. if (textWebSchedDateStart.errorProvider1.GetError(textWebSchedDateStart) != "") { //Don't bother warning the user. It will just be annoying. The red indicator should be sufficient. return; } if (comboWebSchedRecallTypes.SelectedIndex < 0 || comboWebSchedClinic.SelectedIndex < 0 || comboWebSchedProviders.SelectedIndex < 0) { return; } //Protect against re-entry if (_threadFillGridWebSchedTimeSlots != null) { //A thread is already refreshing the time slots grid so we simply need to queue up another refresh once the one thread has finished. _isWebSchedTimeSlotsOutdated = true; return; } _isWebSchedTimeSlotsOutdated = false; DateTime dateStart = PIn.Date(textWebSchedDateStart.Text); RecallType recallType = _listRecallTypes[comboWebSchedRecallTypes.SelectedIndex]; Clinic clinic = _listWebSchedClinics.Find(x => x.ClinicNum == _webSchedClinicNum); //null clinic is treated as unassigned. List <Provider> listProviders = new List <Provider>(_listWebSchedProviders); //Use all providers by default. Provider provider = _listWebSchedProviders.Find(x => x.ProvNum == _webSchedProvNum); if (provider != null) { //Only use the provider that the user picked from the provider picker. listProviders = new List <Provider>() { provider }; } WebSchedTimeSlotArgs webSchedTimeSlotArgs = new WebSchedTimeSlotArgs() { RecallTypeCur = recallType, ClinicCur = clinic, DateStart = dateStart, DateEnd = dateStart.AddDays(30), ListProviders = listProviders }; _threadFillGridWebSchedTimeSlots = new ODThread(GetWebSchedTimeSlotsWorker, webSchedTimeSlotArgs); _threadFillGridWebSchedTimeSlots.Name = "ThreadWebSchedRecallTimeSlots"; _threadFillGridWebSchedTimeSlots.AddExitHandler(GetWebSchedTimeSlotsThreadExitHandler); _threadFillGridWebSchedTimeSlots.AddExceptionHandler(GetWebSchedTimeSlotsExceptionHandler); _threadFillGridWebSchedTimeSlots.Start(true); }
///<summary>Returns a fully formatted string of the most recent unreleased versions, from 1 to 3.</summary> public static string GetLastReleases(int versionsRequested) { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { return(Meth.GetString(MethodBase.GetCurrentMethod(), versionsRequested)); } //Create an ODThread so that we can safely change the database connection settings without affecting the calling method's connection. ODThread odThread = new ODThread(new ODThread.WorkerDelegate((ODThread o) => { //Always set the thread static database connection variables to set the serviceshq db conn. #if DEBUG new DataConnection().SetDbT("localhost", "bugs", "root", "", "", "", DatabaseType.MySql, true); #else new DataConnection().SetDbT("server", "bugs", "root", "", "", "", DatabaseType.MySql, true); #endif string command = "SELECT * FROM versionrelease " + "WHERE DateRelease < '1880-01-01' " //we are only interested in non-released versions. + "AND IsForeign=0 "; //Exclude black listed versions. for (int i = 0; i < _versionsBlackList.Count; i++) { command += "AND (MajorNum,MinorNum) != (" + POut.Int(_versionsBlackList[i].Major) + "," + POut.Int(_versionsBlackList[i].Minor) + ") "; } command += "ORDER BY MajorNum DESC,MinorNum DESC,BuildNum DESC " + "LIMIT 3"; //Might not be 3. List <VersionRelease> releaseList = RefreshAndFill(command); string versionsString = ""; if (releaseList.Count > 2 && versionsRequested > 2) { versionsString += releaseList[2].MajorNum.ToString() + "." + releaseList[2].MinorNum.ToString() + "." + releaseList[2].BuildNum.ToString() + ".0"; } if (releaseList.Count > 1 && versionsRequested > 1) { if (versionsString != "") { versionsString += ";"; } versionsString += releaseList[1].MajorNum.ToString() + "." + releaseList[1].MinorNum.ToString() + "." + releaseList[1].BuildNum.ToString() + ".0"; } if (releaseList.Count > 0) { if (versionsString != "") { versionsString += ";"; } versionsString += releaseList[0].MajorNum.ToString() + "." + releaseList[0].MinorNum.ToString() + "." + releaseList[0].BuildNum.ToString() + ".0"; } o.Tag = versionsString; })); odThread.AddExceptionHandler(new ODThread.ExceptionDelegate((Exception e) => { })); //Do nothing odThread.Name = "versionGetterThread"; odThread.Start(true); if (!odThread.Join(2000)) //Give this thread up to 2 seconds to complete. { return(null); } return(odThread?.Tag?.ToString() ?? ""); //if either odThread or odThread.Tag is null, return empty string }
///<summary>The following test calls setDb within a child thread. This will change the static database connection for all threads. The ///parent thread, or any other thread already alive, should not have their context changed.</summary> public void ODThread_SetDb_ChildContext() { Exception ex = null; string methodName = MethodBase.GetCurrentMethod().Name; string databaseName = POut.String(methodName).ToLower(); string odThreadGroupName = methodName + "_GroupName"; string databaseMain = LargeTableHelper.GetCurrentDatabase(); //should be pointing to a 'unittestXXX' database Assert.IsFalse(string.IsNullOrEmpty(databaseMain)); try { ODThread odThreadAffect = new ODThread((o) => { string databaseBefore = LargeTableHelper.GetCurrentDatabase(); //should be pointing to a 'unittestXXX' database Assert.AreEqual(databaseMain, databaseBefore); ODThread odThreadChangeDb = new ODThread(workerChild => { //The parent thread needs to call SetDb on a different database than the main thread is connected to. CreateDatabaseIfNeeded(databaseName); new DataConnection().SetDb("localhost", databaseName, "root", "", "", "", DatabaseType.MySql); VerifyCurrentDatabaseName(databaseName); }); odThreadChangeDb.AddExceptionHandler(e => ex = e); odThreadChangeDb.Name = MethodBase.GetCurrentMethod().Name + "_Child"; odThreadChangeDb.GroupName = odThreadGroupName; //This thread needs to only start the above thread and then make sure it is still connected to the unittestXXX database when complete. odThreadChangeDb.Start(); odThreadChangeDb.Join(Timeout.Infinite); //Manually join the parent to the main thread so that we know for certain that our child thread exists. VerifyCurrentDatabaseName(databaseMain); }); odThreadAffect.AddExceptionHandler(e => ex = e); odThreadAffect.Name = MethodBase.GetCurrentMethod().Name + "_ThreadAffected"; odThreadAffect.Start(); odThreadAffect.Join(Timeout.Infinite); //The main thread should still be on the original database after this. VerifyCurrentDatabaseName(databaseMain); //Verify that new thread is not affected by the call to SetDb() from the child thread above. //You should only SetDb() once per application instance. //After that, it does nothing to any thread (existing or subsequent) but the thread that calls it. ODThread odThreadChangeDb1 = new ODThread(workerChild => { VerifyCurrentDatabaseName(databaseMain); }); odThreadChangeDb1.AddExceptionHandler(e => ex = e); odThreadChangeDb1.Name = MethodBase.GetCurrentMethod().Name + "_Child"; odThreadChangeDb1.GroupName = odThreadGroupName; odThreadChangeDb1.Start(); odThreadChangeDb1.Join(Timeout.Infinite); //Manually join the parent to the main thread so that we know for certain that our child thread exists. } catch (Exception e) { ex = e; } finally { DropDatabase(databaseName); } Assert.IsNull(ex, ex?.Message); //Asserts do not bubble up as expected to the main thread so do a manual assert at the end of the day. }
///<summary>Shows the saved manually label for 1.5 seconds.</summary> private void ShowManualSaveLabel() { labelSavedManually.Visible = true; ODThread odThread = new ODThread((o) => { Thread.Sleep((int)TimeSpan.FromSeconds(1.5).TotalMilliseconds); this.InvokeIfNotDisposed(() => { labelSavedManually.Visible = false; }); }); odThread.AddExceptionHandler((e) => e.DoNothing()); odThread.Start(); }
///<summary>Adds an exception handler to the thread passed in, starts the thread, and then waits until the thread has finished executing. ///This is just a helper method that will throw any exception that occurs within the thread on the parent (usually main) thread. ///Throws exceptions.</summary> private static void ExecuteThread(ODThread thread) { Exception eFinal = null; thread.AddExceptionHandler((e) => { eFinal = e; }); thread.Start(true); //This is intended to be a blocking call so give the action as long as it needs to complete. thread.Join(Timeout.Infinite); if (eFinal != null) //We are back on the main thread so it is safe to throw. { throw new Exception(eFinal.Message, eFinal); } }
///<summary>Runs the workerDelegate on a separate thread and displays a progress window while the thread is running.</summary> public static void ShowProgressForThread(ODThread.WorkerDelegate workerDelegate, Control parent, string startingMessage = "Please Wait...", ProgBarStyle progStyle = ProgBarStyle.Blocks, string threadName = "ODProgressThread", ODThread.ExceptionDelegate exceptionHandler = null) { ODProgress prog = new ODProgress(Lan.g(parent, startingMessage), progStyle); ODThread thread = new ODThread(workerDelegate); if (exceptionHandler != null) { thread.AddExceptionHandler(exceptionHandler); } thread.Name = threadName; thread.ProgressLog = prog; thread.Start(true); prog.ShowDialog(parent); }
///<summary>Starts the thread which will populate the graph's data. DB context should be set before calling this method.</summary> /// <param name="forceCacheRefesh">Will pass this flag along to the thread which retrieves the cache. If true then cache will be invalidated and re-initialiazed from the db. Use sparingly.</param> /// <param name="onException">Exception handler if something fails. If not set then all exceptions will be swallowed.</param> /// <param name="onThreadDone">Done event handler. Will be invoked when init thread has completed.</param> private void Init(bool forceCacheRefesh = false, ODThread.ExceptionDelegate onException = null, EventHandler onThreadDone = null) { if (_thread != null) { return; } if (onThreadDone == null) { onThreadDone = new EventHandler(delegate(object o, EventArgs e) { }); } if (onException == null) { onException = new ODThread.ExceptionDelegate((Exception e) => { }); } _thread = new ODThread(new ODThread.WorkerDelegate((ODThread x) => { //The thread may have run and return before the window is even ready to display. if (this.IsHandleCreated) { OnThreadStartLocal(this, new EventArgs()); } else { this.HandleCreated += OnThreadStartLocal; } //Alert caller that it's time to start querying the db. OnInit(forceCacheRefesh); })); _thread.Name = "GraphQuantityFilterOverTime.Init"; _thread.AddExceptionHandler(onException); _thread.AddExitHandler(new ODThread.WorkerDelegate((ODThread x) => { try { _thread = null; //The thread may have run and return before the window is even ready to display. if (this.IsHandleCreated) { OnThreadExitLocal(this, new EventArgs()); } else { this.HandleCreated += OnThreadExitLocal; } //Alert caller that db querying is done. onThreadDone(this, new EventArgs()); } catch (Exception) { } })); _thread.Start(true); }
private void LoadDataAsync() { ODThread thread = new ODThread((o) => { _listBugsAll = Bugs.GetAll(); this.BeginInvoke((Action)(FillGridMain)); }); thread.AddExceptionHandler((ex) => { try { this.BeginInvoke((Action)(() => { MessageBox.Show(ex.Message); })); } catch { } }); thread.Start(true); }
///<summary>Launches a splash screen with a progressbar that will listen specifically for ODEvents with the passed in name. ///Returns an ODProgressWindow that has a Close method that should be invoked whenever the progress window should close. ///eventName should be set to the name of the ODEvents that this specific progress window should be processing.</summary> ///<param name="currentForm">The form to activate once the progress is done. If you cannot possibly pass in a form, it is okay to pass in null. ///</param> public static ODProgressWindow ShowProgressSplash(string eventName, Form currentForm) { //Create a splash form with a progress bar on a separate thread to avoid UI lockups bool isFormClosed = false; FormSplash FormS = new FormSplash(eventName); FormS.FormClosed += new FormClosedEventHandler((obj, e) => { isFormClosed = true; }); ODThread odThread = new ODThread(new ODThread.WorkerDelegate((ODThread o) => { //From this point forward, the only way to kill FormSplash is with a DEFCON 1 message via an ODEvent with the corresponding eventName. FormS.ShowDialog(); })); odThread.SetApartmentState(ApartmentState.STA); odThread.AddExceptionHandler(new ODThread.ExceptionDelegate((Exception e) => { })); //Do nothing. odThread.Name = "ProgressSplashThread_" + eventName; odThread.Start(true); return(new ODProgressWindow(new Action(() => { //For progress threads, there is a race condition where the DEFCON 1 event will not get processed. //This is due to the fact that it took the thread longer to instantiate FormProgressStatus than it took the calling method to invoke this action. //Since we don't have access to FormProgressStatus within the thread from here, we simply flag odThread's Tag so that it knows to die. if (odThread != null) { odThread.Tag = true; } //Send the phrase that closes the window in case it is processing events. SplashProgressEvent.Fire(new ODEventArgs(eventName, "DEFCON 1")); if (currentForm != null) { //When the form closed on the other thread it was sometimes causing the application to go behind other applications. Calling Activate() //brings the application back to the front or causes it to flash in the taskbar. DateTime start = DateTime.Now; while (!isFormClosed && (DateTime.Now - start).TotalSeconds < 1) //Wait till the form is closed or for one second { Thread.Sleep(1); } if (!currentForm.IsDisposed) { currentForm.Activate(); } } }))); }
///<summary>The ThreadStatic database context should be inherited by any child thread that is spawned.</summary> public void ODThread_SetDbT_ParentChildDatabaseContext() { Exception ex = null; string methodName = MethodBase.GetCurrentMethod().Name; string databaseName = POut.String(methodName).ToLower(); string odThreadGroupName = methodName + "_GroupName"; //The main thread needs to connect to a unique database that the child thread should NOT end up getting connected to. //Use a query to get our current database context because unit tests utilizes a connection string and we only care about DataConnection.Database string databaseMain = LargeTableHelper.GetCurrentDatabase(); //should be pointing to a 'unittestXXX' database Assert.IsFalse(string.IsNullOrEmpty(databaseMain)); try { ODThread odThreadParent = new ODThread(workerParent => { //The parent thread needs to connect to a database that the main thread is not connected to. CreateDatabaseIfNeeded(databaseName); new DataConnection().SetDbT("localhost", databaseName, "root", "", "", "", DatabaseType.MySql); VerifyCurrentDatabaseName(databaseName); //Now the parent should spawn a child thread which should default to the thread specific database connection from the parent. ODThread odThreadChild = new ODThread(workerChild => { //The child thread should default to the database context of its parent and NOT the database context from the main thread. VerifyCurrentDatabaseName(databaseName); }); odThreadChild.AddExceptionHandler(e => ex = e); odThreadChild.Name = MethodBase.GetCurrentMethod().Name + "_Child"; odThreadChild.GroupName = odThreadGroupName; odThreadChild.Start(); odThreadChild.Join(Timeout.Infinite); VerifyCurrentDatabaseName(databaseName); }); odThreadParent.AddExceptionHandler(e => ex = e); odThreadParent.Name = MethodBase.GetCurrentMethod().Name + "_Parent"; odThreadParent.GroupName = odThreadGroupName; odThreadParent.Start(); odThreadParent.Join(Timeout.Infinite); //Manually join the parent to the main thread so that we know for certain that our child thread exists. VerifyCurrentDatabaseName(databaseMain); } catch (Exception e) { ex = e; } finally { DropDatabase(databaseName); } Assert.IsNull(ex, ex?.Message); //Asserts do not bubble up as expected to the main thread so do a manual assert at the end of the day. }
///<summary>Returns a list of all versions ordered by MajorNum, MinorNum, BuildNum, and IsForeign.</summary> public static List <VersionRelease> Refresh() { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { return(Meth.GetObject <List <VersionRelease> >(MethodBase.GetCurrentMethod())); } //Create an ODThread so that we can safely change the database connection settings without affecting the calling method's connection. ODThread odThread = new ODThread(new ODThread.WorkerDelegate((ODThread o) => { //Always set the thread static database connection variables to set the serviceshq db conn. #if DEBUG new DataConnection().SetDbT("localhost", "bugs", "root", "", "", "", DatabaseType.MySql, true); #else new DataConnection().SetDbT("server", "bugs", "root", "", "", "", DatabaseType.MySql, true); #endif string command = "SELECT * FROM versionrelease "; //Exclude black listed versions. for (int i = 0; i < _versionsBlackList.Count; i++) { if (i == 0) { command += "WHERE "; } else { command += "AND "; } command += "(MajorNum,MinorNum) != (" + POut.Int(_versionsBlackList[i].Major) + "," + POut.Int(_versionsBlackList[i].Minor) + ") "; } //The order is very important to other entites calling this method. command += "ORDER BY MajorNum DESC,MinorNum DESC,BuildNum DESC,IsForeign"; o.Tag = RefreshAndFill(command); })); odThread.AddExceptionHandler(new ODThread.ExceptionDelegate((Exception e) => { })); //Do nothing odThread.Name = "versionGetterThread"; odThread.Start(true); if (!odThread.Join(2000)) //Give this thread up to 2 seconds to complete. { return(null); } return((List <VersionRelease>)odThread.Tag); }
private void StartShouldCloseMonitor() { if (_threadShouldWindowClose != null) { return; } _threadShouldWindowClose = new ODThread(500, (o) => { if (_shouldWindowClose) { ODException.SwallowAnyException(() => { Invoke(new Action(() => { DialogResult = DialogResult.OK; })); }); o.QuitAsync(); } }); _threadShouldWindowClose.Name = "FormConnectionLost_ShouldCloseMonitorThread"; _threadShouldWindowClose.AddExceptionHandler((e) => e.DoNothing()); _threadShouldWindowClose.AddExitHandler((e) => _threadShouldWindowClose = null); _threadShouldWindowClose.Start(); }
///<summary>Gets one EServiceSignalHQ from the serviceshq db located on SERVER184. Returns null in case of failure.</summary> public static EServiceMetrics GetEServiceMetricsFromSignalHQ() { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { return(Meth.GetObject <EServiceMetrics>(MethodBase.GetCurrentMethod())); } //Create an ODThread so that we can safely change the database connection settings without affecting the calling method's connection. ODThread odThread = new ODThread(new ODThread.WorkerDelegate((ODThread o) => { //Always set the thread static database connection variables to set the serviceshq db conn. new DataConnection().SetDbT("server184", "serviceshq", "root", "", "", "", DatabaseType.MySql, true); //See EServiceSignalHQs.GetEServiceMetrics() for details. string command = @"SELECT 0 EServiceSignalNum, h.* FROM eservicesignalhq h WHERE h.ReasonCode=1024 AND h.ReasonCategory=1 AND h.ServiceCode=2 AND h.RegistrationKeyNum=-1 ORDER BY h.SigDateTime DESC LIMIT 1" ; EServiceSignal eServiceSignal = Crud.EServiceSignalCrud.SelectOne(command); EServiceMetrics eServiceMetric = new EServiceMetrics(); if (eServiceSignal != null) { using (XmlReader reader = XmlReader.Create(new System.IO.StringReader(eServiceSignal.Tag))) { eServiceMetric = (EServiceMetrics) new XmlSerializer(typeof(EServiceMetrics)).Deserialize(reader); } eServiceMetric.IsValid = true; } o.Tag = eServiceMetric; })); odThread.AddExceptionHandler(new ODThread.ExceptionDelegate((Exception e) => { })); //Do nothing odThread.Name = "eServiceMetricsThread"; odThread.Start(true); if (!odThread.Join(2000)) //Give this thread up to 2 seconds to complete. { return(null); } EServiceMetrics retVal = (EServiceMetrics)odThread.Tag; return(retVal); }
///<summary></summary> private static string RunWebMethod(Func <string> funcWebMethod) { Exception ex = null; //Create an ODThread so that we can safely change the database connection settings without affecting the calling method's connection. ODThread odThread = new ODThread(new ODThread.WorkerDelegate((ODThread o) => { //Change the thread static remoting role to ServerWeb and then execute the func that was passed in. RemotingClient.SetRemotingRoleT(RemotingRole.ServerWeb); o.Tag = funcWebMethod(); })); odThread.AddExceptionHandler(new ODThread.ExceptionDelegate((Exception e) => { ex = e; //Cannot throw exception here due to still being in a threaded context. })); if (ex != null) { throw ex; //Should never happen because this would be a "web exception" as in the ProcessRequest could not even invoke or something like that. } odThread.Name = "threadMiddleTierUnitTestRunWebMethod"; odThread.Start(true); odThread.Join(System.Threading.Timeout.Infinite); return((string)odThread.Tag); }
///<summary>Perform the given function in the context of the given connectionName db and return a T.</summary> private static T GetT <T>(Func <T> fn, Action aSetConnection) { Exception eFinal = null; //Reference types will be set to null. T ret = default(T); ODThread th = new ODThread(new ODThread.WorkerDelegate((thread) => { aSetConnection(); ret = fn(); })); th.AddExceptionHandler(new ODThread.ExceptionDelegate((e) => { eFinal = e; })); th.Start(true); //This is intended to be a blocking call so give the action as long as it needs to complete. th.Join(System.Threading.Timeout.Infinite); if (eFinal != null) //We are back on the main thread so it is safe to throw. { throw new Exception(eFinal.Message, eFinal); } return(ret); }
public void Reports_GetTable_MySqlUserLow() { Exception ex = null; //Spawn a new thread so that we don't manipulate any global DataConnection settings. ODThread thread = new ODThread(o => { //Prepare some simple queries to verify how both user and user low react. string tempTableName = "tmpreportsunittesttable"; string tempTableDropQuery = $"DROP TABLE IF EXISTS {tempTableName}"; string tempTableCreateQuery = $"CREATE TABLE {tempTableName} (Col1 VARCHAR(1))"; string tempTableShowQuery = $"SHOW TABLES LIKE '{tempTableName}'"; //Make sure that we can create and drop tables as the normal user but cannot do the same thing via Reports.GetTable(). //First, make sure that the regular user works as intended. DataCore.NonQ(tempTableDropQuery); DataCore.NonQ(tempTableCreateQuery); Assert.AreEqual(1, DataCore.GetTable(tempTableShowQuery).Rows.Count, "Root user was not able to create a new table."); DataCore.NonQ(tempTableDropQuery); //Next, make sure that user low cannot create the new table. Required to use the Middle Tier otherwise user low is ignored. DataAction.RunMiddleTierMock(() => { //User low should be able to run SELECT and SHOW commands. if (Reports.GetTable(tempTableShowQuery).Rows.Count != 0) //Should have been dropped via root user above. { throw new ApplicationException("Temporary table was not dropped correctly."); } //Reports.GetTable() should throw an exception due to the lack of the CREATE permission. Swallow it. ODException.SwallowAnyException(() => Reports.GetTable(tempTableCreateQuery)); //User low should not have been able to create the table. if (Reports.GetTable(tempTableShowQuery).Rows.Count != 0) { throw new ApplicationException("User low was able to create a table."); } }); }); thread.AddExceptionHandler(e => { ex = e; }); //This will cause the unit test to fail. thread.Name = "thread" + MethodBase.GetCurrentMethod().Name; thread.Start(); thread.Join(Timeout.Infinite); Assert.IsNull(ex, ex?.Message); }
///<summary>Fires a MiddleTierConnectionEvent of type MiddleTierConnectionLost to notify the main thread that the Middle Tier connection has been lost. ///Wait here until the connection is restored.</summary> private static void RemoteConnectionFailed() { RemotingClient.HasMiddleTierConnectionFailed = true; //Inform all threads that we've lost the MiddleTier connection, so they can handle this appropriately. MiddleTierConnectionEvent.Fire(new MiddleTierConnectionEventArgs(false)); //Keep the current thread stuck here while automatically retrying the connection up until the timeout specified. DateTime beginning = DateTime.Now; ODThread threadRetry = new ODThread(500, (o) => { if (!HasMiddleTierConnectionFailed) { o.QuitAsync(); return; } if ((DateTime.Now - beginning).TotalSeconds >= TimeSpan.FromHours(4).TotalSeconds) { return; //We have reached or exceeded the timeout. Stop automatically retrying and leave it up to a manual retry from the user. } try { if (IsMiddleTierAvailable()) { //Unset HasMiddleTierConnectionFailed flag allowing any blocked Middle Tier communication to continue. RemotingClient.HasMiddleTierConnectionFailed = false; //Also fire a DataConnectionEvent letting everyone who cares know that the connection has been restored. MiddleTierConnectionEvent.Fire(new MiddleTierConnectionEventArgs(true)); o.QuitAsync(); } } catch (Exception ex) { ex.DoNothing(); //Connection has not been restored yet. Wait a little bit and then try again. } }); threadRetry.Name = "MiddleTierConnectionLostAutoRetryThread"; threadRetry.AddExceptionHandler((e) => e.DoNothing()); threadRetry.Start(); //Wait here until the retry thread has finished which is either due to connection being restored or the timeout was reached. threadRetry.Join(Timeout.Infinite); //Wait forever because the retry thread has a timeout within itself. }
private void FormJobDashboard_Load(object sender, EventArgs e) { this.WindowState = FormWindowState.Maximized; Color color0 = Color.DarkSlateGray; Color color1 = Color.LightSlateGray; bool useColor0 = true; foreach (Userod user in Userods.GetUsersByJobRole(JobPerm.Engineer, false).OrderByDescending(x => x.UserName)) { JobManagerUserOverview jobManage; if (useColor0) { jobManage = new JobManagerUserOverview(color0); useColor0 = false; } else { jobManage = new JobManagerUserOverview(color1); useColor0 = true; } jobManage.User = user; jobManage.Dock = DockStyle.Top; this.Controls.Add(jobManage); } //Fills all in memory data from the DB on a seperate thread and then refills controls. ODThread thread = new ODThread((o) => { _listJobsAll = Jobs.GetAll(); Jobs.FillInMemoryLists(_listJobsAll); FillDashboard(); }); thread.AddExceptionHandler((ex) => { MessageBox.Show(ex.Message); }); thread.Start(true); _baseFont = Font; _baseSize = Size; }