Program stops working after minimizing any window in Windows - c#

The program uses two threads: one for collecting the data from USB, and the other writes/displays the data. It seems to work as expected, however, as soon as I minimize/restore any windows on the PC, or press any buttons on the Form, it stops working properly (it stops receiving data). I use link list to keep the data streaming in order. I suspect that maybe the link is lost somewhere because of improper variable declaration. Is there an obvious mistake in my code that could be causing this?
namespace Streamer
{
public class Form1 : System.Windows.Forms.Form
{
Thread tListen;
Thread tDisplay;
public class MY_DATA_BUFFER
{
public byte[] buffer;
public int length;
public MY_DATA_BUFFER nextBuff;
}
private Object thisLock = new Object();
MY_DATA_BUFFER pHead = null;
private static AutoResetEvent DataQueueEvent = new AutoResetEvent(false);
public Form1()
{
// some settings;
}
public unsafe void dataDisplayThread()
{
MY_DATA_BUFFER pWorkingSet = pHead;
if (pWorkingSet == null)
{
// Make sure link list head is initialized...........
do {DataQueueEvent.WaitOne();} while (pHead == null);
// Wait till the two datas are available to write.
if (pHead.nextBuff == null){ DataQueueEvent.WaitOne(); }
if (pWorkingSet == null) { pWorkingSet = pHead; }
}
// Let's start the data write loop
while (bRunning || (pWorkingSet != null))
{
// copy small array to a bigger array
for (int i = 0; i < pWorkingSet.length; i++)
{
pixelValues[pixptr] = pWorkingSet.buffer[i];
pixptr++;
}
if (pixptr >= imWidth * imHeight)
{
pixptr = 0;
// show data in pixelValues
}
// Traverse through the link list data structure.
if (pWorkingSet.nextBuff == null)
{
do
{
if (pWorkingSet.nextBuff == null DataQueueEvent.WaitOne();
lock (thisLock)
{
if (pWorkingSet.nextBuff == null && !bRunning)
break;
}
} while (pWorkingSet.nextBuff == null);
}
// We are good to loop for the next operation
lock (thisLock)
{
pHead = pHead.nextBuff;
pWorkingSet = pHead;
}
}
// All write operation is at completion
pHead = null;
}
public unsafe void XferData(...)
{
MY_DATA_BUFFER tempBuff = null;
for (; bRunning; )
{
// .... do something
// push the data to a link list for
lock (thisLock)
{
MY_DATA_BUFFER newBuff = new MY_DATA_BUFFER();
newBuff.nextBuff = null;
newBuff.buffer = xBufs[k];
newBuff.length = len;
if (tempBuff == null) tempBuff = newBuff;
else
{
tempBuff.nextBuff = newBuff;
tempBuff = newBuff;
}
if (pHead == null) pHead = newBuff;
else
{
DataQueueEvent.Set();
}
}
///////////////////Link List Population completes///////////
Thread.Sleep(0);
} // End infinite loop
}
private void StartBtn_Click(object sender, System.EventArgs e)
{
if (StartBtn.Text.Equals("Start"))
{
// ...
pHead = null;
bRunning = true;
tListen = new Thread(new ThreadStart(XferThread));
tListen.IsBackground = true;
tListen.Priority = ThreadPriority.Highest;
tListen.Start();
tDisplay = new Thread(new ThreadStart(dataDisplayThread));
tDisplay.IsBackground = true;
tDisplay.Priority = ThreadPriority.Highest;
tDisplay.Start();
}
else
{
if (tListen.IsAlive)
{
// ...
bRunning = false;
if (tListen.Join(5000) == false )
tListen.Abort();
tListen = null;
}
if (tDisplay.IsAlive)
{
if (tDisplay.Join(5000) == false )
tDisplay.Abort();
Display = null;
}
}
}
}
}

Related

Updating GUI from multiple threads

I’ve created a user control. In the control I have two methods – sending and receiving some data. Those methods also update the data grid located on the user control.
public void RunTX()
{
tx_run = new Thread(new ThreadStart(SendCanFrames));
if (!tx_run.IsAlive)
{
tx_run.IsBackground = true;
tx_run.Start();
}
}
public void RunRX()
{
rx_run = new Thread(new ThreadStart(ReadCanFrames));
if (!rx_run.IsAlive)
{
rx_run.IsBackground = true;
rx_run.Start();
}
}
private void ReadCanFrames()
{
ushort prev_time_stamp = 0;
while (running)
{
if (CanDevice != null)
CanDevice.Read(ref rx_can_msg, 1, ref read_cnt);
if (read_cnt == 1)
{
read_cnt = 0;
dataGridViewCanRx.Rows[0].Cells[0].Value = rx_can_msg[0].Id.ToString("X");
dataGridViewCanRx.Rows[0].Cells[1].Value = rx_can_msg[0].Size.ToString();
dataGridViewCanRx.Rows[0].Cells[2].Value = BytesToString(rx_can_msg[0].Data);
dataGridViewCanRx.Rows[0].Cells[3].Value = (rx_can_msg[0].TimeStamp - prev_time_stamp).ToString();
prev_time_stamp = rx_can_msg[0].TimeStamp;
}
prev_time_stamp = rx_can_msg[0].TimeStamp;
}
}
private void SendCanFrames()
{
if (tx_can_msg.Length == 0) return;
VSCAN_MSG[] l_msgs = new VSCAN_MSG[2];
while (running)
{
for (int i = 0; i < tx_can_msg.Length; i++)
{
if (can_messages[i].CountRun < can_messages[i].CountMax)
{
can_messages[i].TimeStamp1 = DateTime.Now;
interval = can_messages[i].TimeStamp1 - can_messages[i].TimeStamp2;
if (interval.TotalMilliseconds >= can_messages[i].Period)
{
can_messages[i].TimeStamp2 = DateTime.Now;
l_msgs[0] = tx_can_msg[i];
//send CAN frame
CanDevice.Write(l_msgs, 1, ref written_cnt);
// send immediately
CanDevice.Flush();
can_messages[i].CountRun++;
dataGridViewCanTx.Rows[i].Cells[4].Value = can_messages[i].CountRun.ToString();
}
}
}
}
}
I put four user control instances on the main form and start all four controls.
private void buttonStartAll_Click(object sender, EventArgs e)
{
int can_channel;
for (can_channel = 0; can_channel < 4; can_channel++)
{
if (started[can_channel] == false)
{
if (connected[can_channel] == true)
{
switch (can_channel)
{
case 0:
mainform.userControlCan1.RunTX();
mainform.userControlCan1.RunRX();
started[can_channel] = true;
break;
case 1:
mainform.userControlCan2.RunTX();
mainform.userControlCan2.RunRX();
started[can_channel] = true;
break;
case 2:
mainform.userControlCan3.RunTX();
mainform.userControlCan3.RunRX();
started[can_channel] = true;
break;
case 3:
mainform.userControlCan4.RunTX();
mainform.userControlCan4.RunRX();
started[can_channel] = true;
break;
}
}
}
}
}
All is running, however the GUI freezing and data grids updated by jumps. Why?
I recomend you to look at two key points: Invoke and Application.DoEvents.
First one will help you to update your GUI in main thread instead of child threads.
Have a look at : https://learn.microsoft.com/en-us/dotnet/api/system.reflection.methodbase.invoke?view=netframework-4.8
Application.DoEvents() method tells the system to do other waiting jobs without blocking in some loops. Otherwise updating GUI jobs are postponed and GUI is blocked. Here is the information about this method: https://learn.microsoft.com/tr-tr/dotnet/api/system.windows.forms.application.doevents?view=netframework-4.8
private delegate void dlgUpdateRows(object[] rx_can_msg, int tID);
// Write actual type of rx_can_msg instead of object[] in method signature , second parameter should be your thread id if needed
private void UpdateRows(object[] rx_can_msg, int tID =0)
{
try
{
if (this.InvokeRequired)
{
object[] obj = new object[2];
obj[0] = rx_can_msg;
obj[1] = Thread.CurrentThread.ManagedThreadId;
this.Invoke(new dlgUpdateRows(UpdateRows), obj);
}
else
{
//Here update your datagrid using rx_can_msg
}
//This row is important to avoid blocking
Application.DoEvents();
}
catch (Exception ex)
{
//Do error handling
}
}

Addins interop-access 15-20x faster than in a windows application

I don't know, if StackOverflow is the right place to ask about Performance issues, but I haven't found any better community for this issue yet.
Basically we have two sample programs, one is an addin and one is a winforms program referencing the Word interop.
Both have implemented the same method called GetTabsFromParagraph:
public class SlowExample
{
public static void GetTabsFromParagraph(Paragraph para, Style style, List<Tabulator> tabList, bool getTabsForCase = false)
{
foreach (TabStop tab in para.TabStops)
{
if (tab.CustomTab)
{
bool showTab = true;
foreach (TabStop ts in style.ParagraphFormat.TabStops)
{
if (Math.Abs(ts.Position - tab.Position) < 0.001 &&
ts.Alignment == tab.Alignment)
{
showTab = false;
break;
}
}
if (showTab || getTabsForCase)
{
Tabulator t = new Tabulator
{
Tabulatorausrichtung =
tab.Alignment == WdTabAlignment.wdAlignTabLeft
? TabulatorAusrichtung.Links
: TabulatorAusrichtung.Rechts,
Tabulatorart = TabulatorArt.Tabulator,
Position = tab.Position
};
tabList.Add(t);
}
}
}
if (!getTabsForCase)
{
foreach (TabStop ts in style.ParagraphFormat.TabStops)
{
if (ts.CustomTab)
{
bool showTab = true;
foreach (TabStop tab in para.TabStops)
{
if (Math.Abs(tab.Position - ts.Position) > 0.0001 || tab.Alignment != ts.Alignment)
{
showTab = false;
break;
}
}
if (showTab)
{
Tabulator t = new Tabulator
{
Tabulatorausrichtung = TabulatorAusrichtung.Geloescht,
Tabulatorart = TabulatorArt.Tabulator,
Position = ts.Position
};
tabList.Add(t);
}
}
}
}
if (Math.Abs(para.LeftIndent - style.ParagraphFormat.LeftIndent) > 0.001 || getTabsForCase)
{
Tabulator t = new Tabulator
{
Tabulatorausrichtung = TabulatorAusrichtung.Links,
Tabulatorart = TabulatorArt.Einzug,
Position = para.LeftIndent
};
tabList.Add(t);
}
if (Math.Abs(para.RightIndent - style.ParagraphFormat.RightIndent) > 0.001 || getTabsForCase)
{
Tabulator t = new Tabulator
{
Tabulatorausrichtung = TabulatorAusrichtung.Rechts,
Tabulatorart = TabulatorArt.Einzug,
Position = para.RightIndent
};
tabList.Add(t);
}
if (Math.Abs(para.FirstLineIndent - style.ParagraphFormat.FirstLineIndent) > 0.001 || getTabsForCase)
{
Tabulator t = new Tabulator
{
Tabulatorausrichtung = TabulatorAusrichtung.ErstzeilenEinzug,
Tabulatorart = TabulatorArt.Einzug,
Position = para.FirstLineIndent
};
tabList.Add(t);
}
}
public class Tabulator
{
private TabulatorArt m_Tabulatorart;
private TabulatorAusrichtung m_Tabulatorausrichtung;
private float m_Position;
private bool m_UebernahmeInFolgedokument = false;
public float Position
{
get { return m_Position; }
set { m_Position = value; }
}
public float PositionOrg
{
get;
set;
}
public float PositionInCm
{
get
{
return (m_Position / 28.35F);
}
set
{
m_Position = value * 28.35F;
}
}
public TabulatorArt Tabulatorart
{
get { return m_Tabulatorart; }
set { m_Tabulatorart = value; }
}
public TabulatorAusrichtung Tabulatorausrichtung
{
get { return m_Tabulatorausrichtung; }
set { m_Tabulatorausrichtung = value; }
}
public TabulatorAusrichtung TabulatorausrichtungOrg
{
get;
set;
}
public bool UebernahmeInFolgedokument
{
get { return m_UebernahmeInFolgedokument; }
set { m_UebernahmeInFolgedokument = value; }
}
}
public enum TabulatorArt
{
Invalid = 0,
Tabulator = 1,
Einzug = 2
}
public enum TabulatorAusrichtung
{
Invalid = 0,
Links = 1,
Rechts = 2,
ErstzeilenEinzug = 3,
Geloescht = 4,
}
}
In each of the both programs, I load up a Application, open up a document with a few paragraphs and tabs and run this method for each paragraph like this:
private void TestSlowMethod(Word.Document document)
{
Word.Paragraphs documentParagraphs = document.Paragraphs;
List<Tabulator> tabList = new List<Tabulator>();
long swElapsedMilliseconds = 0;
foreach (Word.Paragraph documentParagraph in documentParagraphs)
{
Word.Style style = documentParagraph.get_Style();
Stopwatch sw = new Stopwatch();
sw.Start();
SlowExample.GetTabsFromParagraph(documentParagraph, style, tabList, true);
sw.Stop();
swElapsedMilliseconds += sw.ElapsedMilliseconds;
Debug.WriteLine(sw.ElapsedMilliseconds + "\r\n");
}
MessageBox.Show("Total ms: " + swElapsedMilliseconds);
Debug.WriteLine("Done...");
}
What I found out is the addin is running throw all of this 10-20 times faster.
Addin: 20-30 ms per call
WinForms tool: 200-300 ms per call
Why is that? My assumption would be, that the addin runs in the same context / process than the word application. But is that the real reason?
And can we fix that? Our software moved from addin to WPF + Interop-Word.
Thanks in advance!
Some performance fixes:
Check getTabsForCase sooner here:
if (tab.CustomTab)
{
bool showTab = true;
if (getTabsForCase) //insert this here, no need to run if getTabsForCase.
foreach (TabStop ts in style.ParagraphFormat.TabStops)
{
if (Math.Abs(ts.Position - tab.Position) < 0.001 &&
ts.Alignment == tab.Alignment)
{
showTab = false;
break;
}
}
if (showTab || getTabsForCase)
{
Tabulator t = new Tabulator
{
Tabulatorausrichtung =
tab.Alignment == WdTabAlignment.wdAlignTabLeft
? TabulatorAusrichtung.Links
: TabulatorAusrichtung.Rechts,
Tabulatorart = TabulatorArt.Tabulator,
Position = tab.Position
};
tabList.Add(t);
}
}
Similarly, put the check on getTabsForCase before all calculations in if statements:
//see getTabsForCase goes first
if (getTabsForCase || Math.Abs(para.LeftIndent - style.ParagraphFormat.LeftIndent) > 0.001)
Fix all of those conditionals to have getTabsForCase first - then the rest of the statement won't need to evaluate.

Thread Method Outrunning ProgressChanged

I have a simple application that executes a function in a separate thread via a BackgroundWorker and am running into issues. I am collecting a string array of values and passing that back to my ProgressChanged event via the ReportProgress method and I'm running into a problem where the thread continues and is so fast, it outruns the ProgressChanged event and overwrites the values before they can be added to a grid. Below is my code...
Button Click Event Fires my thread...
private void LoadButton_Click(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(WorkingPathTextBox.Text))
{
this.dataGridView1.Rows.Clear();
this.progressBar1.Visible = true;
this.LoadButton.Visible = false;
this.BrowseButton.Enabled = false;
this.WorkingPathTextBox.Enabled = false;
this.CancelBtn.Visible = true;
this.ProcessingLabel.Visible = true;
beginTime = DateTime.Now;
WorkflowCleanup wc = new WorkflowCleanup();
wc.WorkflowPath = this.WorkingPathTextBox.Text;
backgroundWorker1.RunWorkerAsync(wc);
}
}
In the DoWork, it loads the class where my work exists...
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
System.ComponentModel.BackgroundWorker worker;
worker = (System.ComponentModel.BackgroundWorker)sender;
// Get the Words object and call the main method.
WorkflowCleanup wc = (WorkflowCleanup)e.Argument;
wc.LoadAssemblies(worker, e);
wc.LoadDataDefinitions(worker, e);
wc.LoadDataDefinitionsDirty(worker, e);
wc.LoadProcesses(worker, e);
wc.LoadProcessesDirty(worker, e);
wc.LoadWorkflows(worker, e);
// wc.UpdateWorkflows(worker, e);
}
WorkflowCleanup class...the ReportProgress in stuck right in the middle of the try/catch because I could not figure out what was causing the problem. So, I moved it in the try, and even had to add a Thread.Sleep(100) to slow the process down to give the ProgressChanged event time enough to add the row of data I passed it to the grid before it was overridden...
namespace WorkflowMaintenance
{
public class WorkflowCleanup
{
private int errorCount = 0;
private int fixCount = 0;
public class Workflow
{
// code truncated
}
public class WorkflowAssembly
{
// code truncated
}
public class DataDefinition
{
// code truncated
}
public class CurrentState
{
public int Percentage;
public string StateString;
public List<string[]> ProcessResults;
public string[] Result;
public int ErrorCount;
public int FixCount;
}
public void LoadAssemblies(System.ComponentModel.BackgroundWorker worker, System.ComponentModel.DoWorkEventArgs e)
{
CurrentState state = new CurrentState();
fixCount = 0;
errorCount = 0;
string[] asmbfiles = System.IO.Directory.GetFiles(WorkflowPath + "\\Assemblies", "*.asmb", System.IO.SearchOption.AllDirectories);
int asmbIndex = 0;
Assemblies = new List<WorkflowAssembly>();
// Assemblies (NEW)
foreach (string asmb in asmbfiles)
{
if (worker.CancellationPending)
{
e.Cancel = true;
break;
}
else
{
//results = new List<string[]>();
asmbIndex += 1;
int percentage = (asmbIndex * 100) / asmbfiles.Length;
state.StateString = string.Format("Loading Assemblies... {0}%", percentage);
state.Percentage = percentage;
try
{
XDocument xdoc = XDocument.Load(asmb);
XElement asmbElement = xdoc.Descendants(wf + "assembly").First();
XElement asmbTypes = asmbElement.Element(wf + "types");
string asmbid = asmbElement.Attribute("id").Value;
string asmbname = asmbElement.Element(wf + "name").Value;
string asmbpath = asmbElement.Element(wf + "assemblyPath").Value;
Assemblies.Add(new WorkflowAssembly() { ID = asmbid, Name = asmbname, FileName = asmb, AssemblyPath = asmbpath, Types = asmbTypes });
//results.Add(new string[] { "SUCCESS", "ASSEMBLY PROCESSED SUCCESSFULLY", asmbname, asmbid, null, asmb });
state.Result = new string[] { "SUCCESS", "ASSEMBLY PROCESSED SUCCESSFULLY", asmbname, asmbid, null, asmb };
fixCount += 1;
//if (results != null && results.Count > 0)
//{
// state.ProcessResult = results;
//}
state.FixCount = fixCount;
state.ErrorCount = errorCount;
worker.ReportProgress(percentage, state);
Thread.Sleep(100);
}
catch (Exception)
{
// need to report the exception...
errorCount += 1;
}
finally
{
//if (results != null && results.Count > 0)
//{
// state.ProcessResult = results;
//}
//state.FixCount = fixCount;
//state.ErrorCount = errorCount;
//worker.ReportProgress(percentage, state);
}
}
}
}
}
}
ProgressChanged Event...
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
// This method runs on the main thread.
WorkflowCleanup.CurrentState state = (WorkflowCleanup.CurrentState)e.UserState;
this.progressBar1.Value = state.Percentage;
this.ProcessingLabel.Text = state.StateString;
this.errorLabel.Text = string.Format("Errors: {0}", state.ErrorCount);
this.fixLabel.Text = string.Format("Fixed: {0}", state.FixCount);
this.ElapsedTimeLabel.Text = string.Format("Elapsed Time: {0}", GetProgressElapsedString());
if (state.Result != null)
{
this.dataGridView1.Rows.Add(state.Result);
}
}
Problem...the problem is that if I have 3 files in the folder (named Assembly1, Assembly2, and Assembly3), the output in the grid shows that all three are named Assembly3. The only way I could fix this was to tell the Thread to sleep. This is not an option as I have to run this for a folder that has approximately 18,000 files and having to sleep for a millisecond would take forever. BUT, I need to get valid results. Help please :-)
Rather than creating the state object outside the loop and mutating it in each iteration, create a new instance for each iteration. This can be done by simply moving the declaration of the variable inside the loop.

Prevent task being executed again while it is still running

Boys and Girls,
I got this method (task) that gets executed when I select a node in a treeview. It retreives data from a database and puts in a ReportControl (Codejock).
What I need is to prevent that this method (task) gets executed again while it is still running.
I've been experimenting with booleans set to false when starts and set to true if finishes but that doesn't work for some reason.......
here is the code:
the event where the method gets executed:
private void tvObjects_AfterSelect(object sender, TreeViewEventArgs e)
{
try
{
tvObjects.PreseveTreeState = true;
tvObjects.SaveTreeState();
tvObjects.SelectedNode.BackColor = Color.FromArgb(191, 210, 234);
AllowPreview = false;
WordPreviewer.UnloadPreviewHandler();
viewer1.Image = null;
rcDocumenten.ClearContent();
rcEmail.ClearContent();
var n = e.Node as ExtendedTreeNode;
tvObjects.CurrentNode = e.Node;
SelectedObjectNode = n;
WordPreviewer.FileName = null;
if (n != null)
{
Document.SetDossierNummer(n.DossierNr);
}
var selNode = e.Node as ExtendedTreeNode;
if (selNode != null && selNode.DossierNode)
{
if (selNode.IsFolder)
{
DossierNr = Convert.ToInt32(selNode.DossierNr);
SelectedObjectNode = selNode;
var col = new col();
col.CreateCurrentDossierDocumentsList(Convert.ToInt32(selNode.DossierNr.ToString()),
selNode.Tag.ToString());
col.CreateCurrentEmailList(selNode.DossierNr, Convert.ToInt32(selNode.Tag.ToString()));
var t =
new Thread(
() =>
rcDocumenten_Populate(Convert.ToInt32(selNode.DossierNr.ToString()),
selNode.Tag.ToString()));
t.Start();
var t2 = new Thread(
() => rcEmail_Populate(selNode.DossierNr, Convert.ToInt32(selNode.Tag.ToString())));
t2.Start();
tcDocumenten.SelectedTab = selNode.Text.Contains("Email") ? tpEmail : tpDocumenten;
}
else
{
tpDocumenten.Text = #"Documenten (0)";
tpEmail.Text = #"Emails (0)";
SelectedBestandId = -1;
SelectedBestandsNaam = string.Empty;
SelectedEmailId = -1;
SelectedEmailOnderwerp = string.Empty;
}
}
else if (selNode != null && selNode.PersonalNode)
{
if (!selNode.IsMedewerker)
{
var t =
new Thread(
() => rcDocumenten_PersoonlijkeMappenPopulate(Convert.ToInt32(selNode.Tag.ToString())));
t.Start();
}
}
}
catch (InvalidOperationException iex)
{
MessageBox.Show(iex.ToString());
}
catch (Exception ex)
{
var dmsEx = new DmsException("Fout tijdens het uitvoeren event AfterSelect tvObjects ", "VDocumenten (tvObjects Event: AfterSelect)", ex);
ExceptionLogger.LogError(dmsEx);
}
}
the method that should not run twice:
public void rcDocumenten_PersoonlijkeMappenPopulate(int personalFolderId)
{
try
{
AllowPreview = false;
var oc = new col();
rcDocumenten.FocusedRow = null;
oc.CreateCurrentPersoonlijkeDocumentsList(personalFolderId);
UpdateUI(false);
if (rcDocumenten.InvokeRequired)
{
rcDocumenten.Invoke((MethodInvoker)delegate
{
rcDocumenten.Records.DeleteAll();
rcDocumenten.Redraw();
_gegevensLaden = new GegevensLaden(this);
_gegevensLaden.Show();
//Documenten uit Database ophalen
_gegevensLaden.progressbar.Maximum = col.ListPersoonlijkeDocuments.Count;
foreach (var document in col.ListPersoonlijkeDocuments)
{
var versie = Convert.ToDecimal(document.Versie.ToString());
if (document.OriBestandId == 0)
{
//Record toevoegen
rcDocumenten_Persoonlijk_AddRecord(document.BestandId, document.BestandsNaam, versie,
document.DatumToevoeg, document.DatumUitcheck, document.UitgechecktDoor, document.Eigenaar,
document.DocumentType, document.DocumentProgres);
}
_gegevensLaden.progressbar.Value = _gegevensLaden.progressbar.Value + 1;
_gegevensLaden.progressbar.Update();
}
var aantalRecords = 0;
for (var i = 0; i < rcDocumenten.Records.Count; i++)
{
aantalRecords++;
for (var j = 0; j < rcDocumenten.Records[i].Childs.Count; j++)
{
aantalRecords++;
}
}
tpDocumenten.Text = #"Documenten (" + aantalRecords + #")";
rcDocumenten.Populate();
Invoke(new UpdateUIDelegate(UpdateUI), new object[] { true });
});
}
//"dd-MM-yyyy HH:mm:ss"
AllowPreview = true;
}
catch (Exception ex)
{
var dmsEx = new DmsException("Fout bij de populatie van Report Control", "VDocumenten (rcDocumenten_Persoonlijk_Populate)", ex);
ExceptionLogger.LogError(dmsEx);
}
}
You can check if the thread/task has completed. Change the thread creation to use a Task
_t =
Task.Factory.StartNew(
() =>
rcDocumenten_Populate(Convert.ToInt32(selNode.DossierNr.ToString()),
selNode.Tag.ToString()));
Then you can keep the Task around in the class scope. As you see above, I called it _t.
private Task _t; // documenten vullen achtergrond thread
Now, instead of blindly starting the Task, check if the Task should be started.
if (_t == null || _t.IsCompleted) {
That would solve your current issue.

Debugging a windows form application

Im making a chat program that saves the messages in files like pub0.zzc, all computers that are using it will be connected to the hard drive that these files are in, so its fine. The method data.Chat.Read(MessageTypes type, string Channel) infinite loops through a try catch statement till it returns the messages. I used this before and works perfectly. But, my code was hard to manage so instead of just putting text boxes into the window and using the code each time, i created a user control (MessageViewer). It works fine, once again when I run it, BUT it freezes VS whenever I try to use the designer on the window housing the control. the probelm isnt the window because when i delete the control its fine. I think the possible errors are at RefreshMessages() and the Refresher_Tick(...)
Refresher.Stop() and .Start() is also not it, worked fine before
so here is the code:
private void Refresher_Tick(object sender, EventArgs e)
{
Refresher.Stop();
int RefreshRate = 4;
bool Live = true;
if (RefreshRateChoice == "Manual")
{
Live = false;
RefreshRate = 1;
}
else if (RefreshRateChoice == "4 ( Default )")
{
Live = true;
RefreshRate = 4;
}
else
{
Live = true;
RefreshRate = Convert.ToInt32(RefreshRateChoice);
}
if (data.Chat.Read(MessageType, ChannelChoice) != ContentPresenter.Text && Live)
{
RefreshMessages();
}
Refresher.Interval = RefreshRate;
Refresher.Start();
}
public void RefreshMessages() {
if (data.Chat.Read(MessageType, ChannelChoice) != ContentPresenter.Text)
{
ContentPresenter.Text = data.Chat.Read(MessageType, ChannelChoice);
}
}
and if you need it:
public static string Read(MessageTypes Type, string Channel)
{
string Loc;
if (Type == MessageTypes.Public && (Channel == "1" || Channel == "2"))
{
return "Can not view this channel, only post to it.";
}
if (Type == MessageTypes.Public)
{
Loc = data.AssetsFolder + "\\pub" + Channel + ".zzc";
}
else if (Type == MessageTypes.Private)
{
Loc = data.AssetsFolder + "\\" + Channel + ".zzpc";
}
else if (Type == MessageTypes.Game)
{
Loc = data.AssetsFolder;
}
else
{
Loc = data.AssetsFolder;
}
while (true)
{
try
{
String MessageList = "";
StreamReader MessageReader = new StreamReader(Loc);
string EncMessages = MessageReader.ReadToEnd();
MessageReader.Dispose();
List<string> EncMsgList = EncMessages.Split(';').ToList();
for (int i = 1; i < EncMsgList.Count; i++)
{
MessageList += data.Encodings.Decrypt(EncMsgList[i], Palettes.Message) + "\n";
}
return MessageList;
}
catch
{
// Do nothing
}
}
}
You say that it "freezes."
In your Read method you have a while(true) loop with an embedded try...catch block, but the catch never returns you from that method. If you keep throwing the same exception, you'll continue to loop over and over which could be where you are freezing.
At least to prove that is the case, put a return in you catch or some diagnostic code to indicate if that is the case.

Categories