我有一個計時器,它觸發一個定時事件,該事件遍歷 aTreeView并 ping 與每個節點關聯的所有 IP 地址。
我希望這在后臺在一個單獨的執行緒上完成。我(可能錯誤地)認為 OnTimedEvent 存在于 UI 的單獨執行緒上。
但是,當我的程式啟動時,它是回應式的。然后,一旦定時事件觸發 UI 變得無回應,不會崩潰但不會恢復回應,直到程式在除錯器中停止并再次運行。
為了獲得所需的行為,我一直在搞亂,async但是await我無法做到這一點。
這是我當前初始化計時器的方式。
public Form1()
{
InitializeComponent();
StartTimer();
}
private async void StartTimer()
{
aTimer = new System.Timers.Timer(15000);
await Task.Run(() => aTimer.Elapsed = OnTimedEvent);
aTimer.AutoReset = true;
aTimer.Enabled = true;
aTimer.SynchronizingObject = this;
}
和 OnEventTimed 方法
private async void OnTimedEvent(Object source, ElapsedEventArgs e)
{
// Iterate through all root nodes
foreach (TreeNode tn in mainTree.Nodes)
{
TreeNodeCollection rootNodes = ((TreeNode)tn).Nodes;
foreach (TreeNode node in rootNodes)
{
// Create ping object
System.Net.NetworkInformation.Ping pinger = new();
PingReply pingReply;
if (node.Tag != null)
{
pingReply = pinger.Send(node.Tag.ToString());
if (pingReply.Status.ToString().Contains("Success"))
{
UpdateUI(node, 1); // If successful, set the image index to show green
}
else if (pingReply.Status.ToString().Contains("Failed"))
{
UpdateUI(node, 2);
}
}
}
// Iterate through all the children of the 'root' nodes
foreach (TreeNode child in tn.Nodes)
{
// Extract all nodes from these children
TreeNodeCollection myNodes = ((TreeNode)child).Nodes;
// Create ping object
System.Net.NetworkInformation.Ping pinger = new();
PingReply pingReply;
// Iterate through each of the nodes, send a ping request and then update the UI based on the result of the ping
foreach (TreeNode node in myNodes)
{
if (node.Tag != null)
{
pingReply = pinger.Send(node.Tag.ToString());
if (pingReply.Status.ToString().Contains("Success"))
{
UpdateUI(node, 1); // If successful, set the image index to show green
}
else if (pingReply.Status.ToString().Contains("Failed"))
{
UpdateUI(node, 2);
}
}
}
}
}
}
我正在嘗試使用await Task.Run(() => aTimer.Elapsed = OnTimedEvent);,但它并沒有給我我期望任何幫助的行為
uj5u.com熱心網友回復:
我的建議是拋棄調皮的System.Timers.Timer,改用普通的System.Windows.Forms.Timer。然后在Tick事件處理程式中,只需卸載ThreadPool您不想在 UI 執行緒上發生的任何作業。所有與 UI 控制元件的互動都應保留在 UI 執行緒上。這是一個(未經測驗的)示例:
private async void timer_Tick(object sender, EventArgs e)
{
timer.Enabled = false;
//...
if (node.Tag != null)
{
string ip = node.Tag.ToString();
PingReply pingReply = await Task.Run(() => pinger.Send(ip));
if (pingReply.Status == IPStatus.Success)
node.ImageIndex = 1;
else
node.ImageIndex = 2;
}
//...
timer.Enabled = true;
}
這Task.Run是進行卸載的方法。的動作在Task.Run上呼叫ThreadPool。呼叫的結果在 UI 執行緒上被封送回,通過awaiting 結果Task<PingReply>。
請注意代理如何Task.Run絲毫沒有接觸TreeNodeUI 元素。它獲取型別的引數string,并回傳 的結果PingReply。所有與 UI 相關的作業都專門在 UI 執行緒上執行。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/524044.html
標籤:C#形式异步等待
