我在執行緒方面幾乎沒有經驗,所以請多多包涵。我正在制作一個監視/測驗工具,它監視硬體傳感器并使用親和掩碼和 for 回圈來逐個回圈運行全負載單核壓力測驗。問題是,當用戶開始測驗并設定了親和性時,它不會只將測驗方法分配給該核心,而是分配整個程式,這意味著 UI 只能在當前測驗的核心上運行滿載。我想很明顯,UI 只是在測驗期間停止,輸出監控資料的標簽被凍結,而在測驗期間獲得相關讀數至關重要,因為這是該程式的主要目的。
經過一些研究,我認為我需要使用執行緒,但我以前從未使用過它。這是我的縮短代碼。問題是,當我在任何包含標簽的方法上使用執行緒時,它會拋出錯誤“跨執行緒操作無效:控制'CPUTempTDie'從創建它的執行緒以外的執行緒訪問”。我嘗試在新執行緒中啟動報告傳感器,但沒有幫助。我真的試圖在一個新執行緒中開始涉及的每個方法和標簽,但它要么無濟于事,要么控制分數(分數 - 是 TestMethod 回傳的結果,以將其與正確的數字進行比較以確認穩定性)或程式只是跳過代碼的一部分,然后說“完成”。
問題是:是否可以只設定TestingMethod一個特定的核心,允許程式的其余部分(包括 UI)使用任何其他免費核心,如果沒有,我應該在一個新執行緒中開始什么來讓 UI 更新在負載下?
//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;
}
澄清:盡管鏈接的執行緒沒有回答我的問題,但我的問題已作為重復項關閉。我要求重新打開它,因為:
雖然鏈接執行緒中提到的“大約 2000 到 3000 次呼叫的大量遠程呼叫”在某些硬體上可能很繁重,但這與在 while(true) 回圈中通過計算敲擊 CPU 不同,后者會從任何如果 UI 位于同一個內核上,那么這種硬體對 UI 毫無意義。
據稱我復制的執行緒中建議的解決方案不能解決問題,而我的原始問題完全不同:我無法弄清楚必須在任務中放入什么才能使 UI 在負載下順利運行。
我的帖子下評論中的建議也沒有回答這個問題。我嘗試了 Panagiotis Kanavos 的解決方案(見下文),但問題仍然存在:
while (true)
{
await Task.Delay(500);
await Task.Run(() => sesnor.ReportSensors());
}
在研究了類似的主題之后,似乎沒有一個能解決我的特定問題。
uj5u.com熱心網友回復:
您正在為 UI 執行緒設定 CPU 親和性,然后在同一執行緒上運行測驗例程,這樣您的 UI 在測驗期間掛起是有意義的。在您開始實際執行測驗例程之前,簡化事情并確保您的 UI/執行緒正常作業。
private int TestingMethod()
{
// set affinity for current thread here when ready
// mock a busy thread by sleeping
System.Threading.Thread.Sleep( 15 * 1000 );
return 42;
}
// don't use `async void`
private async Task PerCoreTest()
{
TestLabel.Text = "Running...";
// we're in the UI thread, so we want to run
// the test in another thread. run a new
// task to do so, await result so the continuation
// will execute back in the UI thread
var score = await Task.Run(() => TestingMethod());
TestLabel.Text = score.ToString();
}
private async Task TestButton_Click(object sender, EventArgs e)
{
await PerCoreTest();
}
很好很簡單。將其他內容添加到每隔一秒左右更新一次的表單中,或者添加一個您可以單擊以驗證 UI 在測驗例程運行時正確更新的按鈕。
一旦您確認 UI 沒有鎖定,您就可以開始在您的測驗例程中添加內容。我建議首先獲得一個沒有處理器親和力的作業測驗例程。
private int TestingMethod()
{
var score = 0;
// set affinity for current thread here when ready
do
{
// your cpu-frying logic
}
while( /* sentinel condition */ )
return score;
}
同樣,在測驗期間驗證 UI 是否回應,您還可以驗證您的一個核心是否被濫用。一旦所有這些都得到驗證,您就可以在方法的實作中設定執行緒關聯TestingMethod()(將其抽象到另一個方法呼叫是可以的,只要它是從TestingMethod' 的主體中呼叫的并且不在一個Task或另一個執行緒中運行。您可以將掩碼TestingMethod作為方法的引數傳入PerCoreTest。
這應該讓你走上正確的軌道,做你想做的事。如果您打算在未來繼續使用它,我建議您花一些時間閱讀一般的多執行緒和 .NET 的執行緒/異步編程模型。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/418160.html
標籤:
下一篇:子元素的簡單定位問題
