public override int GetTimeleft(ThreadControl client) { int index = IndexOf(client); if (index == -1) { return(-1); } lock (timerList) { TimerObject obj = timerList[index]; return(obj.Timeleft); } }
/* * private bool ModeNeedsSystemClock() * { * return ( * AlgoTraderState.Mode == AlgoTraderModes.Live || * AlgoTraderState.Mode == AlgoTraderModes.Paper || * AlgoTraderState.Mode == AlgoTraderModes.FakeLive * ); * } */ public static void WaitFor(int hour, int minute, ThreadControl tc) { int lastSecond = 0; int currentSecond = 0; while (!AlgoTraderState.CurrentTime.IsOnOrPassed(hour, minute) && tc.CheckNotStopped()) { currentSecond = DateTime.UtcNow.Second; if (currentSecond != lastSecond) { lastSecond = currentSecond; tc.Log.AddLine("Waiting for " + hour.ToString("D2") + ":" + minute.ToString("D2") + ". It's currently " + AlgoTraderState.CurrentTime.GetTime().ToString(), Verbosity.Normal); } } }
public static void RefreshNoDataDaysAndSlapCache(ThreadControl tc) { ZonedDateTime ie = SystemClock.Instance.GetCurrentInstant().InZone(UCDT.TimeZones.Eastern); // set the current date to two days ago via eastern timezone DateTime dt = new DateTime(ie.Year, ie.Month, ie.Day, 0, 0, 0, DateTimeKind.Unspecified).AddDays(-2); // ZonedDateTime zdt = UCDT.ZonedDateTimetoZonedDateTime(currentDate, UCDT.TimeZones.Eastern); List <FD> noDataDays = new List <FD>(); while (dt.Year > 2018 && tc.CheckNotStopped()) { tc.Log.AddLine("Checking: " + dt.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture)); if (!StockAPI.Methods.DateHasData(dt.Year, dt.Month, dt.Day, false)) { FD fd = new FD(dt); tc.Log.AddLine("Found a day with no data: " + fd.ToStringLong()); noDataDays.Add(fd); } dt = dt.AddDays(-1); } if (tc.CheckNotStopped()) { DBMethods.RefreshDaysTracker(noDataDays, "NoData"); noDataDays.Sort(); for (int n = 0; n < Global.State.DataTracker.NoDataDays.Count; n++) { // check if we didn't find one that was found before if (noDataDays.BinarySearch(Global.State.DataTracker.NoDataDays[n]) < 0) { tc.Log.AddLine("FOUND A DAY IN THE OLD DATA THAT'S NOT IN THE NEW DATA: " + Global.State.DataTracker.NoDataDays[n].ToStringLong()); // This means that the scan before got a false nodataday. // Could be API error or something. // DELETE ANY CACHED DAY FOR THIS DAY BECAUSE WE MAY HAVE CACHED EMPTY NODES } } App.InitDataTracker(); } }
public virtual void testConcurrentExclusiveCorrelationToDifferentExecutions() { InvocationLogListener.reset(); // given a process instance ProcessInstance instance1 = runtimeService.startProcessInstanceByKey("testProcess"); ProcessInstance instance2 = runtimeService.startProcessInstanceByKey("testProcess"); // and two threads correlating in parallel to each of the two instances ThreadControl thread1 = executeControllableCommand(new ControllableMessageCorrelationCommand("Message", instance1.Id, true)); thread1.reportInterrupts(); ThreadControl thread2 = executeControllableCommand(new ControllableMessageCorrelationCommand("Message", instance2.Id, true)); thread2.reportInterrupts(); // both threads open a transaction and wait before correlating the message thread1.waitForSync(); thread2.waitForSync(); // thread one correlates and acquires the exclusive lock on the event subscription of instance1 thread1.makeContinue(); thread1.waitForSync(); // the service task was executed once assertEquals(1, InvocationLogListener.Invocations); // thread two correlates and acquires the exclusive lock on the event subscription of instance2 // depending on the database and locking used, this may block thread2 thread2.makeContinue(); // thread 1 completes successfully thread1.waitUntilDone(); assertNull(thread1.Exception); // thread2 should be able to continue at least after thread1 has finished and released its lock thread2.waitForSync(); // the service task was executed the second time assertEquals(2, InvocationLogListener.Invocations); // thread 2 completes successfully thread2.waitUntilDone(); assertNull(thread2.Exception); // the follow-up task was reached in both instances assertEquals(2, taskService.createTaskQuery().taskDefinitionKey("afterMessageUserTask").count()); }
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes: //ORIGINAL LINE: @Deployment public void testConcurrentEndExecutionListener() public virtual void testConcurrentEndExecutionListener() { InvocationLogListener.reset(); // given a process instance runtimeService.startProcessInstanceByKey("testProcess"); IList <Execution> tasks = runtimeService.createExecutionQuery().messageEventSubscriptionName("Message").list(); // two tasks waiting for the message assertEquals(2, tasks.Count); // start first thread and wait in the second execution end listener ThreadControl thread1 = executeControllableCommand(new ControllableMessageEventReceivedCommand(tasks[0].Id, "Message", true)); thread1.reportInterrupts(); thread1.waitForSync(); // the counting execution listener was executed on task 1 assertEquals(1, InvocationLogListener.Invocations); // start second thread and complete the task ThreadControl thread2 = executeControllableCommand(new ControllableMessageEventReceivedCommand(tasks[1].Id, "Message", false)); thread2.waitForSync(); thread2.waitUntilDone(); // the counting execution listener was executed on task 1 and 2 assertEquals(2, InvocationLogListener.Invocations); // continue with thread 1 thread1.makeContinueAndWaitForSync(); // the counting execution listener was not executed again assertEquals(2, InvocationLogListener.Invocations); // try to complete thread 1 thread1.waitUntilDone(); // thread 1 was rolled back with an optimistic locking exception Exception exception = thread1.Exception; assertNotNull(exception); assertTrue(exception is OptimisticLockingException); // the execution listener was not executed again assertEquals(2, InvocationLogListener.Invocations); }
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes: //ORIGINAL LINE: @Before public void setUp() throws Exception //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET: public virtual void setUp() { jobExecutor1 = (ControllableJobExecutor)((ProcessEngineConfigurationImpl)engineRule.ProcessEngine.ProcessEngineConfiguration).JobExecutor; jobExecutor1.MaxJobsPerAcquisition = DEFAULT_NUM_JOBS_TO_ACQUIRE; jobExecutor1.BackoffTimeInMillis = BASE_BACKOFF_TIME; jobExecutor1.MaxBackoff = MAX_BACKOFF_TIME; jobExecutor1.BackoffDecreaseThreshold = BACKOFF_DECREASE_THRESHOLD; acquisitionThread1 = jobExecutor1.AcquisitionThreadControl; jobExecutor2 = new ControllableJobExecutor((ProcessEngineImpl)engineRule.ProcessEngine); jobExecutor2.MaxJobsPerAcquisition = DEFAULT_NUM_JOBS_TO_ACQUIRE; jobExecutor2.BackoffTimeInMillis = BASE_BACKOFF_TIME; jobExecutor2.MaxBackoff = MAX_BACKOFF_TIME; jobExecutor2.BackoffDecreaseThreshold = BACKOFF_DECREASE_THRESHOLD; acquisitionThread2 = jobExecutor2.AcquisitionThreadControl; }
/// <summary> /// リストにクライアントを追加。 /// 既に同じクライアントが登録されていれば何もしない。 /// </summary> /// <param name="client">自動更新の対象とするクライアント</param> public override void Add(ThreadControl client) { if (client == null) { throw new ArgumentNullException("client"); } if (list.IndexOf(client) == -1) { // 完了イベントに登録 client.Complete += new CompleteEventHandler(OnComplete); list.Add(client); } if (! timer.Enabled) timer.Start(); }
public void AddService(Type contract, Type concrete, ServiceLifetime lifeCycle, Func <Container, object> initializer, dynamic instance) { var success = ThreadControl.DoubleLock(_synclock, () => _builders.DoesNotContainKey(contract), () => AddBuilder(contract, concrete, lifeCycle, initializer, instance)); if (!success) { throw new IocRegistrationException( $"Type {contract.FullName}: has already been registered with this Ioc container"); } }
/** 添加离线事务 */ public void addOfflineWork(ClientOfflineWorkData data) { data.workIndex = ++_currentIndex; data.workTime = DateControl.getTimeMillis(); ThreadControl.addAssistFunc(() => { _offlineWorkListData.index = data.workIndex; _offlineWorkListData.list.add(data); }); //当前在线 if (GameC.player.system.isOnline()) { SendClientOfflineWorkRequest.create(data).send(); } }
public static void PrepareSocketStreamForWatchSymbols(ThreadControl tc) { /* * Log.AddLine("Preparing socket stream for watch symbols", Log.Verbosity.Minimal); * * List<string> watchSymbols = CL.DB.Methods.GetAllWatchedSymbols(); * * CurrentSymbols.Clear(); * CurrentSymbols.AddRange(watchSymbols); * * List<string> unsubscribeList = AllSymbols.FindAll(s => !watchSymbols.Contains(s)); * * SocketManager.Unsubscribe(unsubscribeList); * * ts.TrySignalEndedIt(); */ }
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET: //ORIGINAL LINE: @Override protected void tearDown() throws Exception protected internal override void tearDown() { // wait for all spawned threads to end //JAVA TO C# CONVERTER WARNING: Java wildcard generics have no direct equivalent in .NET: //ORIGINAL LINE: for (ControllableCommand<?> controllableCommand : controllableCommands) foreach (ControllableCommand <object> controllableCommand in controllableCommands) { ThreadControl threadControl = controllableCommand.monitor; threadControl.executingThread.Interrupt(); threadControl.executingThread.Join(); } // clear the test thread's interruption state Thread.interrupted(); base.tearDown(); }
public virtual void FAILING_testConcurrentExclusiveCorrelationToDifferentExecutionsCase2() { InvocationLogListener.reset(); // given a process instance IProcessInstance instance1 = runtimeService.StartProcessInstanceByKey("testProcess"); IProcessInstance instance2 = runtimeService.StartProcessInstanceByKey("testProcess"); // and two threads correlating in parallel to each of the two instances ThreadControl thread1 = ExecuteControllableCommand(new ControllableMessageCorrelationCommand("Message", instance1.Id, true)); thread1.ReportInterrupts(); ThreadControl thread2 = ExecuteControllableCommand(new ControllableMessageCorrelationCommand("Message", instance2.Id, true)); thread2.ReportInterrupts(); // both threads open a transaction and wait before correlating the message thread1.WaitForSync(); thread2.WaitForSync(); // thread one correlates and acquires the exclusive lock on the event subscription of instance1 thread1.MakeContinue(); thread1.WaitForSync(); // the service task was executed once Assert.AreEqual(1, InvocationLogListener.Invocations); // thread two correlates and acquires the exclusive lock on the event subscription of instance2 thread2.MakeContinue(); // FIXME: this does not return on sql server due to locking thread2.WaitForSync(); // the service task was executed the second time Assert.AreEqual(2, InvocationLogListener.Invocations); // thread 2 completes successfully, even though it acquired its lock after thread 1 thread2.WaitUntilDone(); Assert.IsNull(thread2.Exception); // thread 1 completes successfully thread1.WaitUntilDone(); Assert.IsNull(thread1.Exception); // the follow-up task was reached in both instances Assert.AreEqual(2, taskService.CreateTaskQuery(c => c.TaskDefinitionKey == "afterMessageUserTask").Count()); }
public virtual void testConcurrentMixedCorrelation() { InvocationLogListener.reset(); // given a process instance runtimeService.startProcessInstanceByKey("testProcess"); // and two threads correlating in parallel (one exclusive, one non-exclusive) ThreadControl thread1 = executeControllableCommand(new ControllableMessageCorrelationCommand("Message", true)); thread1.reportInterrupts(); ThreadControl thread2 = executeControllableCommand(new ControllableMessageCorrelationCommand("Message", false)); thread2.reportInterrupts(); // both threads open a transaction and wait before correlating the message thread1.waitForSync(); thread2.waitForSync(); // thread one correlates and acquires the exclusive lock thread1.makeContinue(); thread1.waitForSync(); // thread two correlates since it does not need a pessimistic lock thread2.makeContinue(); thread2.waitForSync(); // the service task was executed twice assertEquals(2, InvocationLogListener.Invocations); // the first thread ends its transaction and releases the lock; the event subscription is now gone thread1.waitUntilDone(); assertNull(thread1.Exception); Task afterMessageTask = taskService.createTaskQuery().singleResult(); assertEquals(afterMessageTask.TaskDefinitionKey, "afterMessageUserTask"); // thread two attempts to end its transaction and fails with optimistic locking thread2.makeContinue(); thread2.waitForSync(); assertTrue(thread2.Exception != null); assertTrue(thread2.Exception is OptimisticLockingException); }
private void doWrite() { ClientPlayerLocalCacheData data = GameC.factory.createClientPlayerLocalCacheData(); data.copy(_data); //缓存一手 string path = _savePath; ThreadControl.addIOFunc(() => { _stream.clear(); _stream.writeVersion(ShineGlobal.playerSaveVersion); data.writeBytesFull(_stream); FileUtils.writeFileForBytes(path, _stream); }); }
public static void UpdateHistoricalTicks(ThreadControl tc) { tc.Log.AddLine("Starting update historical ticks", Verbosity.Minimal); ZonedDateTime ie = SystemClock.Instance.GetCurrentInstant().InZone(UCDT.TimeZones.Eastern); // set the current date to yesterday via eastern timezone just to be safe DateTime currentDate = new DateTime(ie.Year, ie.Month, ie.Day, 0, 0, 0, DateTimeKind.Utc).AddDays(-335); while (tc.CheckNotStopped()) { FD fd = new FD(currentDate); UpdateHistoricalTicksByDay(Global.State.AllSymbols, fd, false, tc); currentDate = currentDate.AddDays(-1); } }
/// <summary> /// 更新イベント発生 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void OnTimer(object sender, ElapsedEventArgs e) { // Timer timer = (Timer)sender; // timer.Stop(); try { current.Stop(); ThreadControl thread = current.Thread; if (thread.IsOpen) { thread.Reload(); } } catch (Exception ex) { TwinDll.Output(ex); } }
private ThreadControl StartButtonDown() { var threadCtrl = new ThreadControl { stop = false, wait = false }; new Thread(() => { while (!threadCtrl.stop) { onButtonDown(); threadCtrl.wait = false; Thread.Sleep(600); // TODO: make this configurable threadCtrl.wait = true; } threadCtrl.wait = false; }).Start(); return(threadCtrl); }
public static void CreateTradingStatsDBs(ThreadControl tc) { List <string> symbols = Global.State.AllSymbols; for (int n = 0; n < symbols.Count; n++) { if (DBMethods.TradingStatsDBExists(symbols[n])) { tc.Log.AddLine("[" + symbols[n] + "] Already has a trading stats DB"); } else { DBMethods.CreateTradingStatsDB(symbols[n]); tc.Log.AddLine("[" + symbols[n] + "] Created trading stats DB."); } } }
public virtual void testConcurrentCorrelationFailsWithOptimisticLockingException() { InvocationLogListener.reset(); // given a process instance runtimeService.startProcessInstanceByKey("testProcess"); // and two threads correlating in parallel ThreadControl thread1 = executeControllableCommand(new ControllableMessageCorrelationCommand("Message", false)); thread1.reportInterrupts(); ThreadControl thread2 = executeControllableCommand(new ControllableMessageCorrelationCommand("Message", false)); thread2.reportInterrupts(); // both threads open a transaction and wait before correlating the message thread1.waitForSync(); thread2.waitForSync(); // both threads correlate thread1.makeContinue(); thread2.makeContinue(); thread1.waitForSync(); thread2.waitForSync(); // the service task was executed twice assertEquals(2, InvocationLogListener.Invocations); // the first thread ends its transcation thread1.waitUntilDone(); assertNull(thread1.Exception); Task afterMessageTask = taskService.createTaskQuery().singleResult(); assertEquals(afterMessageTask.TaskDefinitionKey, "afterMessageUserTask"); // the second thread ends its transaction and fails with optimistic locking exception thread2.waitUntilDone(); assertTrue(thread2.Exception != null); assertTrue(thread2.Exception is OptimisticLockingException); }
public static void UpdateSingleDayAndSingleSymbolTicks(string symbol, FD fd, ThreadControl tc) { if (DBMethods.TradesDBExists(symbol) && DBMethods.QuotesDBExists(symbol)) { if (!Global.State.DataTracker.SymbolHasDayData(symbol, fd)) { tc.Log.AddLine("[" + fd.ToString() + "]", Verbosity.Verbose); tc.Log.AddLine("[" + symbol + "] Making trades API calls", Verbosity.Verbose); List <Trade> trades = StockAPI.Methods.GetHistoricTradesFull(symbol, fd.DT.Year, fd.DT.Month, fd.DT.Day); tc.Log.AddLine("[" + symbol + "] Bulk inserting " + trades.Count + " trade(s)", Verbosity.Verbose); int tradesInserted = DBMethods.BulkInsertTrades(trades, symbol); tc.Log.AddLine("[" + symbol + "] Inserted " + tradesInserted + " trade(s)", Verbosity.Normal); tc.Log.AddLine("[" + symbol + "] Making quotes API calls", Verbosity.Verbose); List <Quote> quotes = StockAPI.Methods.GetHistoricQuotesFull(symbol, fd.DT.Year, fd.DT.Month, fd.DT.Day); tc.Log.AddLine("[" + symbol + "] Bulk inserting " + quotes.Count + " quote(s)", Verbosity.Verbose); int quotesInserted = DBMethods.BulkInsertQuotes(quotes, symbol); tc.Log.AddLine("[" + symbol + "] Inserted " + quotesInserted + " quote(s)", Verbosity.Normal); int p = DBMethods.MarkSymbolHasDayData(symbol, fd.DT.Month, fd.DT.Day, fd.DT.Year); tc.Log.AddLine("[" + symbol + "] Marked symbol has data (" + p + ")", Verbosity.Minimal); } else { tc.Log.AddLine("[" + symbol + "] Already has data for this date."); } } else { tc.Log.AddLine("[" + symbol + "] DBs not found"); } }
/// <summary> /// タイマーが発生したらキューから取り出し更新 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void OnTimer(object sender, ElapsedEventArgs e) { timer.Stop(); if (list.Count > 0) { // 更新対象のアイテムを取得 ThreadControl thread = (ThreadControl)list[0]; // スレッドが開かれていて、読み込み中でない場合のみ更新 if (thread.IsOpen) { thread.Reload(); } // スレッドが開かれていなければ削除 else { list.Remove(thread); } } }
/// <summary> /// In this test, we run two transactions concurrently. /// The transactions have the following behavior: /// /// (1) INSERT row into a table /// (2) SELECT ALL rows from that table /// /// We execute it with two threads in the following interleaving: /// /// Thread 1 Thread 2 /// ======== ======== /// ------INSERT--------------------------- | /// ---------------------------INSERT------ | /// ---------------------------SELECT------ v time /// ------SELECT--------------------------- /// /// Deadlocks may occur if readers are not properly isolated from writers. /// /// </summary> public virtual void testTransactionIsolation() { thread1 = executeControllableCommand(new TestCommand("p1")); // wait for Thread 1 to perform INSERT thread1.waitForSync(); thread2 = executeControllableCommand(new TestCommand("p2")); // wait for Thread 2 to perform INSERT thread2.waitForSync(); // wait for Thread 2 to perform SELECT thread2.makeContinue(); // wait for Thread 1 to perform same SELECT => deadlock thread1.makeContinue(); thread2.waitForSync(); thread1.waitForSync(); }
/// <summary> /// リストにクライアントを追加。 /// 既に同じクライアントが登録されていれば何もしない。 /// </summary> /// <param name="client">自動更新の対象とするクライアント</param> public override void Add(ThreadControl client) { if (client == null) { throw new ArgumentNullException("client"); } if (IndexOf(client) == -1) { // イベントを登録 client.Complete += new CompleteEventHandler(OnComplete); timerCollection.Add(new TimerObject(client, Interval, new ElapsedEventHandler(OnTimer))); } if (!running) { Increment(); } }
public void FireEvents(float pwr) { this.pwr = pwr; if (!buttonDown) { if (pwr < min) { min = pwr; } if (pwr > min + downThresh) { if (onButtonDown != null) { threadCtrl = StartButtonDown(); } buttonDown = true; max = pwr; } } else // ButtonDown { if (pwr > max) { max = pwr; } if (pwr < max - upThresh) { if (threadCtrl != null) { threadCtrl.Stop(); } if (onButtonUp != null) { onButtonUp(); } buttonDown = false; min = pwr; } } }
public virtual void testConcurrentFetchAndDelete() { // given string processInstanceId = deployAndStartProcess(PROCESS_WITH_USERTASK, Variables.createVariables().putValue(VARIABLE_NAME, VARIABLE_VALUE)).Id; ThreadControl asyncThread = executeControllableCommand(new AsyncThread(this, processInstanceId)); asyncThread.waitForSync(); commandExecutor.execute(new CommandAnonymousInnerClass(this)); // assume assertThat(historyService.createHistoricVariableInstanceQuery().singleResult(), nullValue()); // when asyncThread.makeContinue(); asyncThread.waitUntilDone(); // then assertThat(runtimeService.createVariableInstanceQuery().singleResult().Name, @is(VARIABLE_NAME)); assertThat((string)runtimeService.createVariableInstanceQuery().singleResult().Value, @is(ANOTHER_VARIABLE_VALUE)); }
/// <summary> /// リストにクライアントを追加。 /// 既に同じクライアントが登録されていれば何もしない。 /// </summary> /// <param name="client">自動更新の対象とするクライアント</param> public override void Add(ThreadControl client) { if (client == null) { throw new ArgumentNullException("client"); } if (IndexOf(client) == -1) { client.Complete += new CompleteEventHandler(OnComplete); TimerObject timer = new TimerObject(client, Interval, new ElapsedEventHandler(OnTimer)); lock (timerList) { timerList.Add(timer); } timer.Start(); } }
public virtual void testHistoryOptimisticLockingExceptionsNotSkipped() { // given processEngine.ProcessEngineConfiguration.SkipHistoryOptimisticLockingExceptions = false; string processInstanceId = deployAndStartProcess(PROCESS_WITH_USERTASK, Variables.createVariables().putValue(VARIABLE_NAME, VARIABLE_VALUE)).Id; ThreadControl asyncThread = executeControllableCommand(new AsyncThread(this, processInstanceId)); asyncThread.reportInterrupts(); asyncThread.waitForSync(); commandExecutor.execute(new CommandAnonymousInnerClass(this)); // assume assertThat(historyService.createHistoricVariableInstanceQuery().singleResult(), nullValue()); asyncThread.waitUntilDone(); // then assertTextPresent("Entity was updated by another transaction concurrently.", asyncThread.Exception.Message); }
/// <summary> /// リストからクライアントを削除。 /// 指定したクライアントがリストに存在しなければ何もしない。 /// </summary> /// <param name="client">自動更新の対象から外すクライアント</param> public override void Remove(ThreadControl client) { if (client == null) { throw new ArgumentNullException("client"); } int index = IndexOf(client); if (index != -1) { // イベントを削除 client.Complete -= new CompleteEventHandler(OnComplete); lock (timerList) { TimerObject timer = timerList[index]; timer.Dispose(); timerList.Remove(timer); } } }
/** 接受服务发送序号 */ public void receiveIndex(int sendIndex) { //如果不足,赋值(来解决多客户端互相离线登录的序号问题) if (_currentIndex < sendIndex) { _currentIndex = sendIndex; } ThreadControl.addAssistFunc(() => { ClientOfflineWorkData data; int find = -1; SList <ClientOfflineWorkData> list = _offlineWorkListData.list; for (int i = 0, len = list.size(); i < len; i++) { data = list.get(i); if (data.workIndex > sendIndex) { find = i; break; } } if (find == -1) { list.clear(); } else { list.removeRange(0, find); } }); }
/// <summary> /// Updates the ThreadList /// </summary> private void LoadThreads() { ThreadsPanel.Children.Clear(); try { var threadListQuery = SQLServer.MSSelectDataDictionary("SELECT a.*,b.messagecontent as Message,b.Timestamp as SendTime,b.participantid as sender FROM whldata.messenger_threads a Left Join (SELECT m1.* FROM whldata.messenger_messages m1 LEFT JOIN whldata.messenger_messages m2 ON (m1.threadid = m2.threadid AND m1.messageid < m2.messageid) WHERE m2.messageid IS NULL) b on b.threadid=a.threadId WHERE (a.participantid='"+ AuthdEmployee.PayrollId.ToString() + "') ORDER BY b.timestamp DESC;"); if (threadListQuery == null) { throw new Exception("SQL Query Failed"); } foreach (var result in threadListQuery) { var checkList = CheckThreadUsers(int.Parse(result["threadid"].ToString())); if (checkList.Count > 0) { var refcontrol = new ThreadControl { ThreadId = int.Parse(result["threadid"].ToString()), ThreadUsers = { Text = "" } }; foreach (var user in checkList) { refcontrol.ThreadUsers.Text += user.FullName + ","; } refcontrol.ThreadUsers.Text = refcontrol.ThreadUsers.Text.Trim().TrimEnd(','); refcontrol.LastMessage.Text = result["message"].ToString(); refcontrol.MouseUp += HandleThreadClick; refcontrol.InitializeComponent(); ThreadsPanel.Children.Add(refcontrol); } } } catch (Exception exception) { Console.WriteLine(exception); } }