你好,我有一個winform應用程式,它由25個文本框組成,這些文本框表示實時收到的值,同時它們下面有標簽,顯示這些值的最小最大和平均流動,用紅色箭頭顯示
。現在,當應用程式啟動時,它在每個文本框和它的標簽中填充資料,延遲1秒。因此,它需要7到8秒的時間才能完全填充資料。
我想要的是將填充文本框和標簽的任務分為兩部分。
我試著用它進行多執行緒處理,但它對我不起作用
到目前為止,我的代碼我的代碼
Thread mmathread;
while (start)
{
try (開始)。
{
RPM_TEXT.Text = ReadRPM().ToString() " rpm"/span>;
mmathread = new Thread(() => mma(rpm_list, ReadRPM(), RPM_mma) )。
mmathread.Start()。
}
catch { }
try { EL_TEXT.Text = ReadEngineLoad().ToString() " %"/span>;
mmathread = new Thread(() => mma(el_list, ReadEngineLoad(), EL_mma) );
mmathread.Start()。
}
catch { }
try { ECT_TEXT.Text = ReadCoolantTemp().ToString() " ℃";
mmathread = new Thread(() => mma(ect_list, ReadCoolantTemp(), ECT_mma))。
mmathread.Start()。
}
catch { }
}
函式定義是
private void mma(List< int> parameter_list, int parameter, Label label)
{
if (parameter_list.Count == 9) { parameter_list.Add(引數)。
parameter_list.RemoveAt(0); }
else { parameter_list.Add(parameter); }
minpara = parameter_list.Min();
maxpara = parameter_list.Max();
avrgpara = parameter_list.Sum() / parameter_list.Count。
label.Text = $"Min = {minpara}, Avg = {avrgpara}, Max = {maxpara}"/span>。
}
如果我直接呼叫這個函式,它會更新標簽,但如果我向它添加執行緒,標簽就不會彈出
uj5u.com熱心網友回復:當使用執行緒作業時,你需要在標簽上使用Invoke。像這樣
label.Invoke((MethodInvoker) delegate () {label. Text = $"Min = {minpara}, Avg = {avrgpara}, Max = {maxpara}"/span>}。
https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.control.invoke?view=net-5.0
uj5u.com熱心網友回復:
你可以使用Task<T>s代替Threads1。Task.Run方法將提供的動作卸載到ThreadPool,而動作的結果隨后可以通過Result屬性的Task< T> 獲得。你可以await的Task<T>s,這樣,當動作在后臺運行時,UI將保持回應。你也可以一次啟動多個任務,這樣動作就會被平行呼叫。在這種情況下,你可以用Task.WhenAll方法來等待所有的并行任務。例子:
while(start)
{
Task delayTask = Task.Delay(TimeSpan.FromSeconds(1) )。
Task<string> task1 = Task.Run(() => ReadRPM() )。
Task<string> task2 = Task.Run(() => ReadEngineLoad() )。
Task<string> task3 = Task.Run(() => ReadCoolantTemp() )。
await Task.WhenAll(task1, task2, task3)。
RPM_TEXT.Text = task1.Result。
EL_TEXT.Text = task2.Result。
ECT_TEXT.Text = task3.Result。
await delayTask。
在這個例子中,我添加了一個Task.Delay任務,以施加每秒一個回圈的最大頻率。
這段代碼必須放在具有async修改器的方法(或事件處理程式)內,以啟用await運算子。
1 我指的是Thread類,而不是thread作為一個概念.
uj5u.com熱心網友回復:
根據@BojanB的回答,你可以使用傳統的WinForms InvokeRequired/Invoke模式。 如果InvokeRequired屬性在非UI執行緒上被評估,則回傳true。 如果一個Invoke呼叫是必需的,那么你只需Invoke相同的呼叫(將呼叫轉移到UI執行緒),它將完成。 如果你這樣做,那么同一個函式就可以從UI執行緒或任何其他執行緒中呼叫。
首先,我創建了這三個輔助函式:
private void SetTextBoxFromThread(TextBox textBox。string contents)。
{
if (InvokeRequired)
{
Invoke(new Action<TextBox, string>(SetTextBoxFromThread), new object[] { textBox, contents }) 。
return;
}
textBox.Text = contents;
}
private string ReadTextBoxFromThread(TextBox textBox)
{
if (InvokeRequired)
{
return (string)Invoke(new Func< TextBox, string>(ReadTextBoxFromThread), new[] { textBox })。)
}
return textBox.Text;
}
private void SetLabelFromThread(Label label, string contents)。
{
if (InvokeRequired)
{
Invoke(new Action<Label, string>(SetLabelFromThread), new object[ ] { label, contents }) 。
return;
}
label.Text = contents;
}
有了這些,我通過使用這個愚蠢的小執行緒函式(與async版本的ThreadStart委托匹配)來測驗它們:
private int isPaused = 0; //像bool一樣使用,int用于明確的原子性。
private async void ThreadFunc()
{
while (isPaused == 0)
{
var now = DateTime.Now;
var str1 = now.ToString("T"/span>);
var str2 = now.ToString("t")。
var str3 = now.ToString("s") 。
SetTextBoxFromThread(textBox1, str1);
SetTextBoxFromThread(textBox2, str2);
SetTextBoxFromThread(textBox3, str3)。
await Task.Delay(1500) 。
SetLabelFromThread(label1, ReadTextBoxFromThread(textBox1))。
SetLabelFromThread(label2, ReadTextBoxFromThread(textBox2))。
SetLabelFromThread(label3, ReadTextBoxFromThread(textBox3))。
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/325302.html
標籤:
