我的WPF程式,需要連線PLC、CCD、RFID、掃碼槍、控制卡
所以我寫了
InitHardware();
private void InitHardware()
{
var tasks = new Task[]
{
//後臺執行緒長連線,不取消令牌
Task.Factory.StartNew(() => InitConnPLC(),CancellationToken.None,TaskCreationOptions.LongRunning,TaskScheduler.Default),
Task.Factory.StartNew(() => InitConnRFId(),CancellationToken.None,TaskCreationOptions.LongRunning,TaskScheduler.Default),
Task.Factory.StartNew(() => InitConnCCd(),CancellationToken.None,TaskCreationOptions.LongRunning,TaskScheduler.Default),
Task.Factory.StartNew(() => InitScanCode(),CancellationToken.None,TaskCreationOptions.LongRunning,TaskScheduler.Default),
Task.Factory.StartNew(() => InitControlCard(),CancellationToken.None,TaskCreationOptions.LongRunning,TaskScheduler.Default),
};
Task.Factory.ContinueWhenAll(tasks, completedTasks =>
{
// 當所有任務完成時的邏輯
foreach (var task in completedTasks)
{
if (task.IsFaulted)
{
// 處理任務異常
Dispatcher.CurrentDispatcher.Invoke(new Action(() =>
{
HandyOrgMessageBox.Info("Task。PLC連線失敗"); //這段程式碼先放著,我在其他地方做了異常處理
}));
}
// 其他所有任務完成時的邏輯
}
});
}
/// <summary>
/// 初始化PLC,為了應對不同公司的風格
/// PLC讀取Ini檔案
/// </summary>
public void InitConnPLC()
{
PlcClient.Current.PlcCount = SysPlc.PlcCount = IniHelper.Current.GetPath("Config/setting.ini").GetSection("PlcCount").ToInt();
PlcClient.Current.DefaultPlc = ObPLC.Where(it => it.IP == IPHelper.LocalIP4FromPLC).First(); //如果一個PLC走這條線,用於前期測試,正式釋出可以不寫DefaultPlc,會自動跟據PlcCount的多少連線
PlcClient.Current.FindRuningPlc = ObPLC.ToArray(); //如果多個PLC走這條線
while (true)
{
Task.Delay(200);
Dispatcher.CurrentDispatcher.Invoke(
new Action(() =>
{
PlcInfo.IsConn = result.IsSuccess;
PlcInfo.PlcName = PlcInfo.IsConn ? "已連線PLC" : "未連線PLC";
})
);
}
}
可以看出我在這5個類似的方法中頻繁更新UI,因為我要和裝置長連線
解決方案1、將更新UI從while中剔除出來,寫在UI執行緒
首先增加一個靜態的全域性變數
public class SysPlc
{
public static bool IsConn {get;set;}
}
那麼 Dispatcher.CurrentDispatcher.Invoke不必頻繁去寫。
修改while
while (true)
{
Task.Delay(200);
var result = PlcClient.Current.ConnectionPLC;
SysPlc.IsConn = result.IsSuccess;
}
然後加入定時器
_dispatcherTimer = new DispatcherTimer();
_dispatcherTimer.Interval = TimeSpan.FromMilliseconds(500);
_dispatcherTimer.Tick += OnTick;
_dispatcherTimer.Start();
在UI執行緒透過全域性靜態傳遞過來的資料更新UI
private void OnTick(object sender, EventArgs e)
{
PlcInfo.PlcName = SysPlc.IsConn ? "已連線PLC" : "未連線PLC";
}