I have literally no experience in threading, so bear with me, please. I'm making a monitoring/testing tool, that monitors hardware sensors and uses affinity masks and for loop to cycle through the cores one by one running a full-load single-core stress test. The problem is, that when the user starts the test, and affinity is set, instead of assigning just the test method to that core, it assigns the entire program, which means UI can run only on the core that is currently tested and is under full load. I guess it's clear that UI is just stalling during the test, and labels that output monitoring data are frozen, while it's crucial to have relevant readings during the test because this is the main purpose of this program.
After some research, I figured that I need to use threading but I never worked with it before. Here is my shortened code. The problem is, that when I use threading on any method that contains labels, it throws the error "Cross-thread operation not valid: Control 'CPUTempTDie' accessed from a thread other than the thread it was created on". I tried to start Report sensors in a new thread, but it doesn't help. I literally tried to start in a new thread every method and label that is involved, but it's either doesn't help or control score (score - is a result returned by TestMethod to compare it with the correct number to confirm stability) or the program just skips some part of the code and just says "Done".
The question is: Is it possible to set just a TestingMethod
to a particular core, allowing the rest of the program (including UI) to use any other free core, and if not, what exactly should I start in a new thread to let UI update under the load?
//the method below updates labels and calls ReportSensors method that reads
//sensors on a timer tick
private void Monitoring()
{
sensor.ReportSensors(); //calls Method that reads sensors
//Two labels below are stalling when TestingMethod runs
CPUTempTDie.Value = (int)sensor.CpuTemp;
FrequencyLabel.Text = sensor.CoreFrequency.ToString("0") + "MHz";
}
private int TestingMethod()
{
while (true)
{
//Performs calculations to generate load, returns the "score"
}
if (timer.Elapsed.TotalSeconds > 60)
{
break;
}
return score;
}
private async void PerCoreTest()
{
try
{
await Task.Delay(3000);
for (int i = 0; i < (numberOfCores); i++)
{
coreCounter++;
Thread.BeginThreadAffinity();
SetThreadAffinityMask(GetCurrentThread(), new IntPtr(intptrVal));
//TestingMethod below being called twice, and results from both runs
//are later compared for consistency.
TestingMethod();
iter1 = score / 10000;
TestingMethod();
iter2 = score / 10000;
maxScore = Math.Max(iter1, iter2);
await Task.Delay(1000);
TestLabel.Text = score.ToString();
//Switches to the next thread mask
}
}
finally
{
Thread.EndThreadAffinity();
}
}
private void TestButton_Click(object sender, EventArgs e)
{
using (Process p = Process.GetCurrentProcess())
p.PriorityClass = ProcessPriorityClass.High;
PerCoreTest();
using (Process p = Process.GetCurrentProcess())
p.PriorityClass = ProcessPriorityClass.Normal;
}
Clarification: My question was closed as a duplicate despite the linked thread doesn't answer my question. I ask to reopen it because:
While "a large number of Remote Calls around 2000 - 3000 calls" mentioned in a linked thread might be heavy on some hardware, it's not the same as hammering the CPU with calculations in the while(true) loop, which squeeze all performance from any kind of hardware living nothing for UI if UI sits on the same core.
Suggested solution in the thread that I allegedly duplicated doesn't resolve the issue, and my original question is completely different: I can not figure out what exactly must be put in a task to make UI run smoothly under the load.
Suggestions from the comments under my thread don't answer the question too. I tried the solution from Panagiotis Kanavos (see below) but the problem persists:
while (true)
{
await Task.Delay(500);
await Task.Run(() => sesnor.ReportSensors());
}
After researching similar topics it seems like none of them address my particular issue.