using Aurora; using Aurora.Util.HislogPlus; using OpenCvSharp; using System; using System.Collections.Generic; using System.Configuration; using System.IO; using System.Threading; using System.Threading.Tasks; using System.Windows; using System.Windows.Media.Imaging; namespace ILSOS_KS.Views.PopUP { public interface IPopupService : IDisposable { void Generation(); void Show(); void Hide(); void UpdateImages1(Mat LeftTop, OpenCvSharp.Rect roi); void UpdateImages2(Mat RightTop, OpenCvSharp.Rect roi); void UpdateImages3(Mat LeftBottom, OpenCvSharp.Rect roi); void UpdateImages4(Mat RightBottom, OpenCvSharp.Rect roi); void SetParameters1(List step); void SetParameters2(List step); void SetParameters3(List step); void SetParameters4(List step); void SetStepLBAD(string str); void SetStepWELDING(string str); } public class PopupService : IPopupService { private static PopupService _instance; private static readonly object _lock = new object(); public static PopupService Instance { get { if (_instance == null) throw new InvalidOperationException("PopupService.Init() 먼저 호출하세요."); return _instance; } } public static void Init() { if (_instance != null) return; lock (_lock) { if (_instance == null) { _instance = new PopupService(); } } } private PopupWindowViewModel _currentViewModel; private PopupUpWindows _currentWindow; private readonly CancellationTokenSource _cts = new CancellationTokenSource(); private PopupService() { // UI 스레드에서 종료 이벤트 등록 if (Application.Current != null) { Application.Current.Dispatcher.BeginInvoke(new Action(() => { Application.Current.Exit += (s, e) => Dispose(); })); } } #region Window 생성/제어 public void Generation() { try { Application.Current.Dispatcher.Invoke(() => { if (_currentWindow == null || !_currentWindow.IsLoaded) { _currentViewModel = new PopupWindowViewModel(); _currentWindow = new PopupUpWindows(_currentViewModel); _currentWindow.Closing += _currentWindow_Closing; } }); } catch (Exception ex) { AsyncLog.E($"[PopupService.Generation 예외] {ex}"); } } private void _currentWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e) { e.Cancel = true; _currentWindow.Hide(); } public void Show() { try { Application.Current.Dispatcher.Invoke(() => { if (_currentWindow == null || !_currentWindow.IsLoaded) Generation(); if (_currentWindow != null) { if (_currentWindow.WindowState == WindowState.Minimized) _currentWindow.WindowState = WindowState.Normal; _currentWindow.Topmost = true; _currentWindow.Show(); _currentWindow.Activate(); _currentWindow.Topmost = false; } }); } catch (Exception ex) { AsyncLog.E($"[PopupService.Show 예외] {ex}"); } } public void Hide() { try { Application.Current.Dispatcher.Invoke(() => { _currentWindow?.Hide(); }); } catch (Exception ex) { AsyncLog.E($"[PopupService.Hide 예외] {ex}"); } } #endregion public void UpdateImages1(Mat LeftTop, OpenCvSharp.Rect roi) { if (_currentViewModel == null || _cts.IsCancellationRequested) return; Task.Run(() => { try { Application.Current.Dispatcher.Invoke(() => { _currentViewModel.SetImages1(LeftTop, roi); }); } catch (Exception ex) { AsyncLog.E($"[PopupService.UpdateImages1 예외] {ex}"); } }, _cts.Token); } public void UpdateImages2(Mat RightTop, OpenCvSharp.Rect roi) { if (_currentViewModel == null || _cts.IsCancellationRequested) return; Task.Run(() => { try { Application.Current.Dispatcher.Invoke(() => { _currentViewModel.SetImages2(RightTop, roi); }); } catch (Exception ex) { AsyncLog.E($"[PopupService.UpdateImages2 예외] {ex}"); } }, _cts.Token); } public void UpdateImages3(Mat LeftBottom, OpenCvSharp.Rect roi) { if (_currentViewModel == null || _cts.IsCancellationRequested) return; Task.Run(() => { try { Application.Current.Dispatcher.Invoke(() => { _currentViewModel.SetImages3(LeftBottom, roi); }); } catch (Exception ex) { AsyncLog.E($"[PopupService.UpdateImages2 예외] {ex}"); } }, _cts.Token); } public void UpdateImages4(Mat RightBottom, OpenCvSharp.Rect roi) { if (_currentViewModel == null || _cts.IsCancellationRequested) return; Task.Run(() => { try { Application.Current.Dispatcher.Invoke(() => { _currentViewModel.SetImages4(RightBottom, roi); }); } catch (Exception ex) { AsyncLog.E($"[PopupService.UpdateImages2 예외] {ex}"); } }, _cts.Token); } public void SetParameters1(List step) { if (_currentViewModel == null || _cts.IsCancellationRequested) return; Task.Run(() => { try { Application.Current.Dispatcher.Invoke(() => _currentViewModel.SetParameters1(step) ); } catch (Exception ex) { AsyncLog.E($"[PopupService.SetParameters1 예외] {ex}"); } }, _cts.Token); } public void SetParameters2(List step) { if (_currentViewModel == null || _cts.IsCancellationRequested) return; Task.Run(() => { try { Application.Current.Dispatcher.Invoke(() => _currentViewModel.SetParameters2(step) ); } catch (Exception ex) { AsyncLog.E($"[PopupService.SetParameters2 예외] {ex}"); } }, _cts.Token); } public void SetParameters3(List step) { if (_currentViewModel == null || _cts.IsCancellationRequested) return; Task.Run(() => { try { Application.Current.Dispatcher.Invoke(() => _currentViewModel.SetParameters3(step) ); } catch (Exception ex) { AsyncLog.E($"[PopupService.SetParameters3 예외] {ex}"); } }, _cts.Token); } public void SetParameters4(List step) { if (_currentViewModel == null || _cts.IsCancellationRequested) return; Task.Run(() => { try { Application.Current.Dispatcher.Invoke(() => _currentViewModel.SetParameters4(step) ); } catch (Exception ex) { AsyncLog.E($"[PopupService.SetParameters4 예외] {ex}"); } }, _cts.Token); } public void SetStepLBAD(string str) { if (_currentViewModel == null || _cts.IsCancellationRequested) return; Task.Run(() => { try { Application.Current.Dispatcher.Invoke(() => _currentViewModel.StepLBAD = str ); } catch (Exception ex) { AsyncLog.E($"[PopupService.SetStepLBAD 예외] {ex}"); } }, _cts.Token); } public void SetStepWELDING(string str) { if (_currentViewModel == null || _cts.IsCancellationRequested) return; Task.Run(() => { try { Application.Current.Dispatcher.Invoke(() => _currentViewModel.StepWELDING = str ); } catch (Exception ex) { AsyncLog.E($"[PopupService.SetStepWELDING 예외] {ex}"); } }, _cts.Token); } #region Dispose public void Dispose() { try { // 1. Task 취소 _cts.Cancel(); _cts.Dispose(); Application.Current.Dispatcher.Invoke(() => { // 2. Window 종료 if (_currentWindow != null) { _currentWindow.Closing -= _currentWindow_Closing; _currentWindow.Close(); _currentWindow = null; } // 3. ViewModel 제거 및 Mat Dispose _currentViewModel?.DisposeImages(); _currentViewModel = null; // 4. GC 강제 GC.Collect(); GC.WaitForPendingFinalizers(); AsyncLog.I("PopupService 종료 및 메모리 해제 완료"); }); } catch (Exception ex) { AsyncLog.E($"[PopupService.Dispose 예외] {ex}"); } } #endregion } }