|
|
@@ -9,6 +9,7 @@ using System;
|
|
|
using System.Collections.Generic;
|
|
|
using System.Drawing;
|
|
|
using System.IO;
|
|
|
+using System.Threading;
|
|
|
using System.Threading.Tasks;
|
|
|
using System.Windows;
|
|
|
using System.Windows.Controls;
|
|
|
@@ -44,6 +45,10 @@ namespace TeamAAS_VP.Views.Home
|
|
|
private readonly IProductService _productService;
|
|
|
private readonly Prism.Services.Dialogs.IDialogService _dialogService;
|
|
|
|
|
|
+ // ====== 异步保存控制 ======
|
|
|
+ private CancellationTokenSource _saveImageCts = new CancellationTokenSource();
|
|
|
+ private readonly SemaphoreSlim _saveSemaphore = new SemaphoreSlim(5, 5);
|
|
|
+
|
|
|
public ShowVisionRender()
|
|
|
{
|
|
|
InitializeComponent();
|
|
|
@@ -57,8 +62,22 @@ namespace TeamAAS_VP.Views.Home
|
|
|
_dialogService = ((Prism.PrismApplicationBase)App.Current).Container.Resolve<Prism.Services.Dialogs.IDialogService>();
|
|
|
|
|
|
viewModel.UpdateLayout += ViewModel_UpdateLayout;
|
|
|
- _eventAggregator.GetEvent<RenderUpdateNotification>().Subscribe(UpdateRenderModuleSource);
|
|
|
+ // ThreadOption.BackgroundThread:Publish() 立即返回,图像处理不等待 UI 更新和文件 I/O
|
|
|
+ _eventAggregator.GetEvent<RenderUpdateNotification>().Subscribe(UpdateRenderModuleSource, ThreadOption.BackgroundThread);
|
|
|
_eventAggregator.GetEvent<ProductChangedNotification>().Subscribe(ProductChanged);
|
|
|
+
|
|
|
+ // 控件卸载时取消所有保存任务,防止页面关闭后仍在写文件导致闪退
|
|
|
+ this.Unloaded += ShowVisionRender_Unloaded;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void ShowVisionRender_Unloaded(object sender, RoutedEventArgs e)
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ _saveImageCts.Cancel();
|
|
|
+ _saveImageCts.Dispose();
|
|
|
+ }
|
|
|
+ catch { }
|
|
|
}
|
|
|
|
|
|
private bool GetView3DUse()
|
|
|
@@ -82,103 +101,158 @@ namespace TeamAAS_VP.Views.Home
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// 更新 2D/3D 显示并触发异步保存。
|
|
|
+ /// 运行在后台线程(ThreadOption.BackgroundThread),不阻塞图像处理主流程。
|
|
|
+ /// </summary>
|
|
|
private void UpdateRenderModuleSource(ShowRender render)
|
|
|
{
|
|
|
- //foreach (var item in vmRenders)
|
|
|
- //{
|
|
|
- // if (item.Key== render.Id)
|
|
|
- // {
|
|
|
- // App.Current.Dispatcher.Invoke(new Action(() =>
|
|
|
- // {
|
|
|
- // item.Value.ModuleSource = render.ModuleSource;
|
|
|
- // }));
|
|
|
- // break;
|
|
|
- // }
|
|
|
- //}
|
|
|
- this.gridRender.Dispatcher.BeginInvoke(new Action(() =>
|
|
|
- {
|
|
|
- if (render == null)
|
|
|
- return;
|
|
|
-
|
|
|
- if (render.Is3DModel == true && GetView3DUse()==true)
|
|
|
- {
|
|
|
- //if (!GetView3DUse())
|
|
|
- // return;
|
|
|
+ if (render == null) return;
|
|
|
|
|
|
- if (!vmRenders.TryGetValue(Get3DKey(render.Id), out var host))
|
|
|
- return;
|
|
|
-
|
|
|
- var display = host.Child as Cognex.VisionPro3D.Cog3DDisplayV2WF;
|
|
|
- if (display == null)
|
|
|
- return;
|
|
|
+ // 【关键】在后台线程深拷贝 ICogImage,防止下一次 ToolBlock.Run() 覆盖像素数据
|
|
|
+ ICogImage imageCopy = null;
|
|
|
+ try
|
|
|
+ {
|
|
|
+ imageCopy = render.Image?.CopyBase(CogImageCopyModeConstants.CopyPixels);
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ LogHelper.WriteLogError("深拷贝 ICogImage 失败", ex);
|
|
|
+ }
|
|
|
|
|
|
- try
|
|
|
- {
|
|
|
- display.Clear();
|
|
|
+ var token = _saveImageCts.Token;
|
|
|
|
|
|
- if (render.RangeImage == null || render.GreyImage == null)
|
|
|
- return;
|
|
|
+ // 派发 UI 更新到 WPF UI 线程(fire-and-forget)
|
|
|
+ this.gridRender.Dispatcher.BeginInvoke(new Action(() =>
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ if (token.IsCancellationRequested) return;
|
|
|
|
|
|
- var rImgG = new Cog3DRangeImageGraphic(render.RangeImage, render.GreyImage);
|
|
|
- display.Add(rImgG, "__default");
|
|
|
- display.FitView();
|
|
|
- }
|
|
|
- catch (System.Windows.Forms.AxHost.InvalidActiveXStateException)
|
|
|
+ // ==== 3D 显示 ====
|
|
|
+ bool is3D = render.Is3DModel && GetView3DUse();
|
|
|
+ if (is3D)
|
|
|
{
|
|
|
+ if (vmRenders.TryGetValue(Get3DKey(render.Id), out var host3D))
|
|
|
+ {
|
|
|
+ if (host3D.Child is Cognex.VisionPro3D.Cog3DDisplayV2WF display3D)
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ display3D.Clear();
|
|
|
+ if (render.RangeImage != null && render.GreyImage != null)
|
|
|
+ {
|
|
|
+ var rImgG = new Cog3DRangeImageGraphic(render.RangeImage, render.GreyImage);
|
|
|
+ display3D.Add(rImgG, "__default");
|
|
|
+ display3D.FitView();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ catch (System.Windows.Forms.AxHost.InvalidActiveXStateException) { }
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- //return;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- if (!vmRenders.TryGetValue(Get2DKey(render.Id), out var host2D))
|
|
|
- return;
|
|
|
+ // ==== 2D 显示 ====
|
|
|
+ if (!vmRenders.TryGetValue(Get2DKey(render.Id), out var host2D))
|
|
|
+ return;
|
|
|
|
|
|
- var recordDisplay = host2D.Child as Cognex.VisionPro.CogRecordDisplay;
|
|
|
- if (recordDisplay == null)
|
|
|
- return;
|
|
|
+ if (!(host2D.Child is CogRecordDisplay recordDisplay))
|
|
|
+ return;
|
|
|
|
|
|
- try
|
|
|
- {
|
|
|
recordDisplay.Record = null;
|
|
|
- recordDisplay.Image = render.Image;
|
|
|
- recordDisplay.StaticGraphics.Clear();
|
|
|
+ recordDisplay.Image = imageCopy; // 深拷贝后的图像
|
|
|
|
|
|
+ recordDisplay.StaticGraphics.Clear();
|
|
|
if (render.Graphic != null)
|
|
|
recordDisplay.StaticGraphics.AddList(render.Graphic, "");
|
|
|
|
|
|
if (render.Record != null)
|
|
|
recordDisplay.Record = render.Record;
|
|
|
+
|
|
|
+ // ==== 异步保存(fire-and-forget,不阻塞 UI 线程) ====
|
|
|
if (render.IsSaveImage)
|
|
|
{
|
|
|
- Bitmap bitmap = null;
|
|
|
+ RequestSaveImage(recordDisplay, imageCopy, render, token);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ catch (System.Windows.Forms.AxHost.InvalidActiveXStateException) { }
|
|
|
+ }));
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 在 WinForms 控件线程上截图,然后后台异步保存。
|
|
|
+ /// </summary>
|
|
|
+ private void RequestSaveImage(
|
|
|
+ CogRecordDisplay recordDisplay,
|
|
|
+ ICogImage imageCopy,
|
|
|
+ ShowRender render,
|
|
|
+ CancellationToken token)
|
|
|
+ {
|
|
|
+ recordDisplay.BeginInvoke(new Action(() =>
|
|
|
+ {
|
|
|
+ Bitmap clonedBitmap = null;
|
|
|
+ try
|
|
|
+ {
|
|
|
+ if (token.IsCancellationRequested) return;
|
|
|
+ if (recordDisplay.IsDisposed || !recordDisplay.IsHandleCreated) return;
|
|
|
+
|
|
|
+ Bitmap uiBitmap = (Bitmap)recordDisplay.CreateContentBitmap(
|
|
|
+ Cognex.VisionPro.Display.CogDisplayContentBitmapConstants.Custom);
|
|
|
+ clonedBitmap = (Bitmap)uiBitmap.Clone();
|
|
|
+ uiBitmap.Dispose();
|
|
|
+
|
|
|
+ var capturedBitmap = clonedBitmap;
|
|
|
+ var capturedRender = render;
|
|
|
+ var capturedImage = imageCopy;
|
|
|
|
|
|
+ Task.Run(async () =>
|
|
|
+ {
|
|
|
+ await _saveSemaphore.WaitAsync(token);
|
|
|
try
|
|
|
{
|
|
|
- bitmap = (Bitmap)recordDisplay.CreateContentBitmap(Cognex.VisionPro.Display.CogDisplayContentBitmapConstants.Custom);
|
|
|
-
|
|
|
- SaveImage(
|
|
|
- render.SaveImageModel,
|
|
|
- render.SaveImagePathModel,
|
|
|
- render.SavePath,
|
|
|
- render.Image,
|
|
|
- bitmap,
|
|
|
- render.Result,
|
|
|
- render.IsCompress,
|
|
|
- render.ImageFileName,
|
|
|
- render.Is3DModel
|
|
|
+ if (token.IsCancellationRequested) return;
|
|
|
+
|
|
|
+ if (string.IsNullOrEmpty(_productService.CurrentProductCode))
|
|
|
+ {
|
|
|
+ _eventAggregator.GetEvent<TaskMessageNotification>()
|
|
|
+ .Publish(new Models.MessageStruct()
|
|
|
+ {
|
|
|
+ Message = "当前产品SN不存在,无法保存图片!",
|
|
|
+ level = MessageLevel.Alarm
|
|
|
+ });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ LogHelper.WriteLogInfo("开始异步保存图像");
|
|
|
+ await SaveImageAsync(
|
|
|
+ capturedRender.SaveImageModel,
|
|
|
+ capturedRender.SaveImagePathModel,
|
|
|
+ capturedRender.SavePath,
|
|
|
+ capturedImage,
|
|
|
+ capturedBitmap,
|
|
|
+ capturedRender.Result,
|
|
|
+ capturedRender.IsCompress,
|
|
|
+ capturedRender.ImageFileName,
|
|
|
+ capturedRender.Is3DModel,
|
|
|
+ token
|
|
|
);
|
|
|
}
|
|
|
- catch
|
|
|
+ catch (OperationCanceledException) { }
|
|
|
+ catch (Exception ex)
|
|
|
{
|
|
|
- try { bitmap?.Dispose(); } catch { }
|
|
|
- throw;
|
|
|
+ LogHelper.WriteLogError("后台保存图像任务出错!", ex);
|
|
|
}
|
|
|
- }
|
|
|
-
|
|
|
+ finally
|
|
|
+ {
|
|
|
+ try { capturedBitmap?.Dispose(); } catch { }
|
|
|
+ _saveSemaphore.Release();
|
|
|
+ }
|
|
|
+ }, token);
|
|
|
}
|
|
|
- catch (System.Windows.Forms.AxHost.InvalidActiveXStateException)
|
|
|
+ catch (Exception ex)
|
|
|
{
|
|
|
+ LogHelper.WriteLogError("RequestSaveImage(UI截图阶段) 出错!", ex);
|
|
|
+ try { clonedBitmap?.Dispose(); } catch { }
|
|
|
}
|
|
|
}));
|
|
|
}
|
|
|
@@ -296,6 +370,15 @@ namespace TeamAAS_VP.Views.Home
|
|
|
Grid grid20 = new Grid();
|
|
|
private void ViewModel_UpdateLayout(System.Collections.ObjectModel.ObservableCollection<Models.ShowRender> obj)
|
|
|
{
|
|
|
+ // 布局刷新前取消旧保存任务
|
|
|
+ try
|
|
|
+ {
|
|
|
+ _saveImageCts.Cancel();
|
|
|
+ _saveImageCts.Dispose();
|
|
|
+ }
|
|
|
+ catch { }
|
|
|
+ _saveImageCts = new CancellationTokenSource();
|
|
|
+
|
|
|
System.Windows.Media.FontFamily font = Application.Current.Resources["DefaultFont"] as System.Windows.Media.FontFamily;
|
|
|
|
|
|
if (vmRenders.Count > 0)
|
|
|
@@ -636,7 +719,20 @@ namespace TeamAAS_VP.Views.Home
|
|
|
/// <summary>
|
|
|
/// 保存图像(保持你原有逻辑不变,补充 Dispose 兜底,防止压缩分支不释放导致闪退)
|
|
|
/// </summary>
|
|
|
- private void SaveImage(ProcedureSaveImageModel saveImageModel, ProcedureSaveImagePathModel saveImagePathModel, string path, ICogImage image, Bitmap reimage, bool result, bool isCompress, string imageFileName,bool is3Dmodel)
|
|
|
+ /// <summary>
|
|
|
+ /// 异步保存图像(调用者已在后台线程,不再嵌套 Task.Run)
|
|
|
+ /// </summary>
|
|
|
+ private async Task SaveImageAsync(
|
|
|
+ ProcedureSaveImageModel saveImageModel,
|
|
|
+ ProcedureSaveImagePathModel saveImagePathModel,
|
|
|
+ string path,
|
|
|
+ ICogImage image,
|
|
|
+ Bitmap reimage,
|
|
|
+ bool result,
|
|
|
+ bool isCompress,
|
|
|
+ string imageFileName,
|
|
|
+ bool is3Dmodel,
|
|
|
+ CancellationToken cancellationToken)
|
|
|
{
|
|
|
if (string.IsNullOrEmpty(path) || string.IsNullOrWhiteSpace(path) || !Path.IsPathRooted(path))
|
|
|
{
|
|
|
@@ -645,236 +741,230 @@ namespace TeamAAS_VP.Views.Home
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- Task.Run(() =>
|
|
|
+ try
|
|
|
{
|
|
|
- try
|
|
|
+ cancellationToken.ThrowIfCancellationRequested();
|
|
|
+
|
|
|
+ DateTime now = DateTime.Now;
|
|
|
+ string imgName = now.ToString("yyyy-MM-dd HH_mm_ss");
|
|
|
+ if (!string.IsNullOrEmpty(imageFileName))
|
|
|
+ {
|
|
|
+ imgName = imageFileName;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (saveImageModel == ProcedureSaveImageModel.Original)
|
|
|
{
|
|
|
- DateTime now = DateTime.Now;
|
|
|
- //图片名
|
|
|
- string imgName = now.ToString("yyyy-MM-dd HH_mm_ss");
|
|
|
- if (!string.IsNullOrEmpty(imageFileName))
|
|
|
+ string Originalpath = $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\{imgName}.bmp";
|
|
|
+
|
|
|
+ if (saveImagePathModel == ProcedureSaveImagePathModel.Month_Day_OkNG_Time)
|
|
|
{
|
|
|
- imgName = imageFileName;
|
|
|
+ Originalpath = result
|
|
|
+ ? $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\OK\\{imgName}.bmp"
|
|
|
+ : $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\NG\\{imgName}.bmp";
|
|
|
}
|
|
|
-
|
|
|
- if (saveImageModel == ProcedureSaveImageModel.Original)
|
|
|
+ else if (saveImagePathModel == ProcedureSaveImagePathModel.Month_Day_Ok_Time)
|
|
|
+ {
|
|
|
+ if (result)
|
|
|
+ Originalpath = $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\OK\\{imgName}.bmp";
|
|
|
+ else
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ else if (saveImagePathModel == ProcedureSaveImagePathModel.Month_Day_Ng_Time)
|
|
|
{
|
|
|
- string Originalpath = $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\{imgName}.bmp";
|
|
|
+ if (!result)
|
|
|
+ Originalpath = $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\NG\\{imgName}.bmp";
|
|
|
+ else
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ else if (saveImagePathModel == ProcedureSaveImagePathModel.Month_Day_Formula_ProductSN_Time)
|
|
|
+ {
|
|
|
+ string formulaName = _productService.GetCurrentProduct().Name;
|
|
|
+ foreach (char c in Path.GetInvalidFileNameChars())
|
|
|
+ formulaName = formulaName.Replace(c, '_');
|
|
|
|
|
|
- if (saveImagePathModel == ProcedureSaveImagePathModel.Month_Day_OkNG_Time)
|
|
|
- {
|
|
|
- Originalpath = result
|
|
|
- ? $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\OK\\{imgName}.bmp"
|
|
|
- : $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\NG\\{imgName}.bmp";
|
|
|
- }
|
|
|
- else if (saveImagePathModel == ProcedureSaveImagePathModel.Month_Day_Ok_Time)
|
|
|
- {
|
|
|
- if (result)
|
|
|
- Originalpath = $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\OK\\{imgName}.bmp";
|
|
|
- else
|
|
|
- return;
|
|
|
- }
|
|
|
- else if (saveImagePathModel == ProcedureSaveImagePathModel.Month_Day_Ng_Time)
|
|
|
- {
|
|
|
- if (!result)
|
|
|
- Originalpath = $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\NG\\{imgName}.bmp";
|
|
|
- else
|
|
|
- return;
|
|
|
- }
|
|
|
- else if (saveImagePathModel == ProcedureSaveImagePathModel.Month_Day_Formula_ProductSN_Time)
|
|
|
- {
|
|
|
- // 当前产品配方名(过滤非法字符)
|
|
|
- string formulaName = _productService.GetCurrentProduct().Name;
|
|
|
- foreach (char c in Path.GetInvalidFileNameChars())
|
|
|
- formulaName = formulaName.Replace(c, '_');
|
|
|
+ string productSN = _productService.CurrentProductCode;
|
|
|
+ foreach (char c in Path.GetInvalidFileNameChars())
|
|
|
+ productSN = productSN.Replace(c, '_');
|
|
|
|
|
|
- // 产品SN(过滤非法字符)
|
|
|
- string productSN = _productService.CurrentProductCode;
|
|
|
- foreach (char c in Path.GetInvalidFileNameChars())
|
|
|
- productSN = productSN.Replace(c, '_');
|
|
|
+ string resultStr = result ? "OK" : "NG";
|
|
|
+ Originalpath = $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\{formulaName}\\{productSN}\\{resultStr}\\{imgName}.bmp";
|
|
|
+ }
|
|
|
|
|
|
- string resultStr = result ? "OK" : "NG";
|
|
|
- Originalpath = $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\{formulaName}\\{productSN}\\{resultStr}\\{imgName}.bmp";
|
|
|
- }
|
|
|
+ cancellationToken.ThrowIfCancellationRequested();
|
|
|
|
|
|
- if (!Directory.Exists(Path.GetDirectoryName(Originalpath)))
|
|
|
- Directory.CreateDirectory(Path.GetDirectoryName(Originalpath));
|
|
|
+ if (!Directory.Exists(Path.GetDirectoryName(Originalpath)))
|
|
|
+ Directory.CreateDirectory(Path.GetDirectoryName(Originalpath));
|
|
|
|
|
|
- using (CogImageFileBMP _cogImageFileTool = new CogImageFileBMP())
|
|
|
- {
|
|
|
- _cogImageFileTool.Open(Originalpath, CogImageFileModeConstants.Write);
|
|
|
- _cogImageFileTool.Append(image);
|
|
|
- _cogImageFileTool.Close();
|
|
|
- }
|
|
|
+ using (CogImageFileBMP _cogImageFileTool = new CogImageFileBMP())
|
|
|
+ {
|
|
|
+ _cogImageFileTool.Open(Originalpath, CogImageFileModeConstants.Write);
|
|
|
+ _cogImageFileTool.Append(image);
|
|
|
+ _cogImageFileTool.Close();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (saveImageModel == ProcedureSaveImageModel.Recorded)
|
|
|
+ {
|
|
|
+ string Recordedpath = $"{path}\\Recored\\{now:yyyy-MM}\\{now:MM-dd}\\{imgName}.bmp";
|
|
|
+
|
|
|
+ if (saveImagePathModel == ProcedureSaveImagePathModel.Month_Day_OkNG_Time)
|
|
|
+ {
|
|
|
+ Recordedpath = result
|
|
|
+ ? $"{path}\\Recored\\{now:yyyy-MM}\\{now:MM-dd}\\OK\\{imgName}.bmp"
|
|
|
+ : $"{path}\\Recored\\{now:yyyy-MM}\\{now:MM-dd}\\NG\\{imgName}.bmp";
|
|
|
}
|
|
|
- else if (saveImageModel == ProcedureSaveImageModel.Recorded)
|
|
|
+ else if (saveImagePathModel == ProcedureSaveImagePathModel.Month_Day_Ok_Time)
|
|
|
{
|
|
|
- string Recordedpath = $"{path}\\Recored\\{now:yyyy-MM}\\{now:MM-dd}\\{imgName}.bmp";
|
|
|
+ if (result)
|
|
|
+ Recordedpath = $"{path}\\Recored\\{now:yyyy-MM}\\{now:MM-dd}\\OK\\{imgName}.bmp";
|
|
|
+ else
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ else if (saveImagePathModel == ProcedureSaveImagePathModel.Month_Day_Ng_Time)
|
|
|
+ {
|
|
|
+ if (!result)
|
|
|
+ Recordedpath = $"{path}\\Recored\\{now:yyyy-MM}\\{now:MM-dd}\\NG\\{imgName}.bmp";
|
|
|
+ else
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ else if (saveImagePathModel == ProcedureSaveImagePathModel.Month_Day_Formula_ProductSN_Time)
|
|
|
+ {
|
|
|
+ string formulaName = _productService.GetCurrentProduct().Name;
|
|
|
+ foreach (char c in Path.GetInvalidFileNameChars())
|
|
|
+ formulaName = formulaName.Replace(c, '_');
|
|
|
|
|
|
- if (saveImagePathModel == ProcedureSaveImagePathModel.Month_Day_OkNG_Time)
|
|
|
- {
|
|
|
- Recordedpath = result
|
|
|
- ? $"{path}\\Recored\\{now:yyyy-MM}\\{now:MM-dd}\\OK\\{imgName}.bmp"
|
|
|
- : $"{path}\\Recored\\{now:yyyy-MM}\\{now:MM-dd}\\NG\\{imgName}.bmp";
|
|
|
- }
|
|
|
- else if (saveImagePathModel == ProcedureSaveImagePathModel.Month_Day_Ok_Time)
|
|
|
- {
|
|
|
- if (result)
|
|
|
- Recordedpath = $"{path}\\Recored\\{now:yyyy-MM}\\{now:MM-dd}\\OK\\{imgName}.bmp";
|
|
|
- else
|
|
|
- return;
|
|
|
- }
|
|
|
- else if (saveImagePathModel == ProcedureSaveImagePathModel.Month_Day_Ng_Time)
|
|
|
- {
|
|
|
- if (!result)
|
|
|
- Recordedpath = $"{path}\\Recored\\{now:yyyy-MM}\\{now:MM-dd}\\NG\\{imgName}.bmp";
|
|
|
- else
|
|
|
- return;
|
|
|
- }
|
|
|
- else if (saveImagePathModel == ProcedureSaveImagePathModel.Month_Day_Formula_ProductSN_Time)
|
|
|
- {
|
|
|
- string formulaName = _productService.GetCurrentProduct().Name;
|
|
|
- foreach (char c in Path.GetInvalidFileNameChars())
|
|
|
- formulaName = formulaName.Replace(c, '_');
|
|
|
+ string productSN = _productService.CurrentProductCode;
|
|
|
+ foreach (char c in Path.GetInvalidFileNameChars())
|
|
|
+ productSN = productSN.Replace(c, '_');
|
|
|
|
|
|
- string productSN = _productService.CurrentProductCode;
|
|
|
- foreach (char c in Path.GetInvalidFileNameChars())
|
|
|
- productSN = productSN.Replace(c, '_');
|
|
|
+ string resultStr = result ? "OK" : "NG";
|
|
|
+ Recordedpath = $"{path}\\Recored\\{now:yyyy-MM}\\{now:MM-dd}\\{formulaName}\\{productSN}\\{resultStr}\\{imgName}.bmp";
|
|
|
+ }
|
|
|
|
|
|
- string resultStr = result ? "OK" : "NG";
|
|
|
- Recordedpath = $"{path}\\Recored\\{now:yyyy-MM}\\{now:MM-dd}\\{formulaName}\\{productSN}\\{resultStr}\\{imgName}.bmp";
|
|
|
- }
|
|
|
+ cancellationToken.ThrowIfCancellationRequested();
|
|
|
+
|
|
|
+ if (!Directory.Exists(Path.GetDirectoryName(Recordedpath)))
|
|
|
+ Directory.CreateDirectory(Path.GetDirectoryName(Recordedpath));
|
|
|
+
|
|
|
+ if (isCompress)
|
|
|
+ {
|
|
|
+ ImageHelper.CompressImage(reimage, Recordedpath, 20);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ reimage.Save(Recordedpath);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (saveImageModel == ProcedureSaveImageModel.OriginalAndRecorded)
|
|
|
+ {
|
|
|
+ string Originalpath = is3Dmodel
|
|
|
+ ? $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\{imgName}.idb"
|
|
|
+ : $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\{imgName}.bmp";
|
|
|
|
|
|
- if (!Directory.Exists(Path.GetDirectoryName(Recordedpath)))
|
|
|
- Directory.CreateDirectory(Path.GetDirectoryName(Recordedpath));
|
|
|
+ string Recordedpath = $"{path}\\Recored\\{now:yyyy-MM}\\{now:MM-dd}\\{imgName}.bmp";
|
|
|
|
|
|
- if (isCompress)
|
|
|
+ if (saveImagePathModel == ProcedureSaveImagePathModel.Month_Day_OkNG_Time)
|
|
|
+ {
|
|
|
+ if (result)
|
|
|
{
|
|
|
- ImageHelper.CompressImage(reimage, Recordedpath, 20);
|
|
|
+ Originalpath = is3Dmodel
|
|
|
+ ? $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\OK\\{imgName}.idb"
|
|
|
+ : $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\OK\\{imgName}.bmp";
|
|
|
+ Recordedpath = $"{path}\\Recored\\{now:yyyy-MM}\\{now:MM-dd}\\OK\\{imgName}.bmp";
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- reimage.Save(Recordedpath);
|
|
|
+ Originalpath = is3Dmodel
|
|
|
+ ? $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\NG\\{imgName}.idb"
|
|
|
+ : $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\NG\\{imgName}.bmp";
|
|
|
+ Recordedpath = $"{path}\\Recored\\{now:yyyy-MM}\\{now:MM-dd}\\NG\\{imgName}.bmp";
|
|
|
}
|
|
|
}
|
|
|
- else if (saveImageModel == ProcedureSaveImageModel.OriginalAndRecorded)
|
|
|
+ else if (saveImagePathModel == ProcedureSaveImagePathModel.Month_Day_Ok_Time)
|
|
|
{
|
|
|
- string Originalpath = "";
|
|
|
- if (is3Dmodel==true)
|
|
|
+ if (result)
|
|
|
{
|
|
|
- Originalpath = $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\{imgName}.idb";
|
|
|
+ Originalpath = is3Dmodel
|
|
|
+ ? $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\OK\\{imgName}.idb"
|
|
|
+ : $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\OK\\{imgName}.bmp";
|
|
|
+ Recordedpath = $"{path}\\Recored\\{now:yyyy-MM}\\{now:MM-dd}\\OK\\{imgName}.bmp";
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- Originalpath = $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\{imgName}.bmp";
|
|
|
- }
|
|
|
- string Recordedpath = $"{path}\\Recored\\{now:yyyy-MM}\\{now:MM-dd}\\{imgName}.bmp";
|
|
|
-
|
|
|
- if (saveImagePathModel == ProcedureSaveImagePathModel.Month_Day_OkNG_Time)
|
|
|
- {
|
|
|
- if (result)
|
|
|
- {
|
|
|
- Originalpath = $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\OK\\{imgName}.bmp";
|
|
|
- Recordedpath = $"{path}\\Recored\\{now:yyyy-MM}\\{now:MM-dd}\\OK\\{imgName}.bmp";
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- Originalpath = $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\NG\\{imgName}.bmp";
|
|
|
- Recordedpath = $"{path}\\Recored\\{now:yyyy-MM}\\{now:MM-dd}\\NG\\{imgName}.bmp";
|
|
|
- }
|
|
|
+ return;
|
|
|
}
|
|
|
- else if (saveImagePathModel == ProcedureSaveImagePathModel.Month_Day_Ok_Time)
|
|
|
+ }
|
|
|
+ else if (saveImagePathModel == ProcedureSaveImagePathModel.Month_Day_Ng_Time)
|
|
|
+ {
|
|
|
+ if (!result)
|
|
|
{
|
|
|
- if (result)
|
|
|
- {
|
|
|
- Originalpath = $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\OK\\{imgName}.bmp";
|
|
|
- Recordedpath = $"{path}\\Recored\\{now:yyyy-MM}\\{now:MM-dd}\\OK\\{imgName}.bmp";
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- return;
|
|
|
- }
|
|
|
+ Originalpath = is3Dmodel
|
|
|
+ ? $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\NG\\{imgName}.idb"
|
|
|
+ : $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\NG\\{imgName}.bmp";
|
|
|
+ Recordedpath = $"{path}\\Recored\\{now:yyyy-MM}\\{now:MM-dd}\\NG\\{imgName}.bmp";
|
|
|
}
|
|
|
- else if (saveImagePathModel == ProcedureSaveImagePathModel.Month_Day_Ng_Time)
|
|
|
+ else
|
|
|
{
|
|
|
- if (!result)
|
|
|
- {
|
|
|
- Originalpath = $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\NG\\{imgName}.bmp";
|
|
|
- Recordedpath = $"{path}\\Recored\\{now:yyyy-MM}\\{now:MM-dd}\\NG\\{imgName}.bmp";
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- return;
|
|
|
- }
|
|
|
+ return;
|
|
|
}
|
|
|
- else if (saveImagePathModel == ProcedureSaveImagePathModel.Month_Day_Formula_ProductSN_Time)
|
|
|
+ }
|
|
|
+ else if (saveImagePathModel == ProcedureSaveImagePathModel.Month_Day_Formula_ProductSN_Time)
|
|
|
+ {
|
|
|
+ string formulaName = _productService.GetCurrentProduct().Name;
|
|
|
+ foreach (char c in Path.GetInvalidFileNameChars())
|
|
|
+ formulaName = formulaName.Replace(c, '_');
|
|
|
+
|
|
|
+ string productSN = _productService.CurrentProductCode;
|
|
|
+ if (productSN != null)
|
|
|
{
|
|
|
- string formulaName = _productService.GetCurrentProduct().Name;
|
|
|
foreach (char c in Path.GetInvalidFileNameChars())
|
|
|
- formulaName = formulaName.Replace(c, '_');
|
|
|
+ productSN = productSN.Replace(c, '_');
|
|
|
+ }
|
|
|
|
|
|
- string productSN = _productService.CurrentProductCode;
|
|
|
- if(productSN!=null )
|
|
|
- {
|
|
|
- foreach (char c in Path.GetInvalidFileNameChars())
|
|
|
- productSN = productSN.Replace(c, '_');
|
|
|
- }
|
|
|
-
|
|
|
+ string resultStr = result ? "OK" : "NG";
|
|
|
+ string ext = is3Dmodel ? ".idb" : ".bmp";
|
|
|
+ Originalpath = $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\{formulaName}\\{productSN}\\{resultStr}\\{imgName}{ext}";
|
|
|
+ Recordedpath = $"{path}\\Recored\\{now:yyyy-MM}\\{now:MM-dd}\\{formulaName}\\{productSN}\\{resultStr}\\{imgName}.bmp";
|
|
|
+ }
|
|
|
|
|
|
- string resultStr = result ? "OK" : "NG";
|
|
|
- if (is3Dmodel == true)
|
|
|
- {
|
|
|
- Originalpath = $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\{formulaName}\\{productSN}\\{resultStr}\\{imgName}.idb";
|
|
|
- //Originalpath = $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\{imgName}.idb";
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- Originalpath = $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\{formulaName}\\{productSN}\\{resultStr}\\{imgName}.bmp";
|
|
|
- //Originalpath = $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\{imgName}.bmp";
|
|
|
- }
|
|
|
- Recordedpath = $"{path}\\Recored\\{now:yyyy-MM}\\{now:MM-dd}\\{formulaName}\\{productSN}\\{resultStr}\\{imgName}.bmp";
|
|
|
- }
|
|
|
+ cancellationToken.ThrowIfCancellationRequested();
|
|
|
|
|
|
- if (!Directory.Exists(Path.GetDirectoryName(Originalpath)))
|
|
|
- Directory.CreateDirectory(Path.GetDirectoryName(Originalpath));
|
|
|
+ if (!Directory.Exists(Path.GetDirectoryName(Originalpath)))
|
|
|
+ Directory.CreateDirectory(Path.GetDirectoryName(Originalpath));
|
|
|
|
|
|
- //using (CogImageFileBMP _cogImageFileTool = new CogImageFileBMP())
|
|
|
- //{
|
|
|
- // _cogImageFileTool.Open(Originalpath, CogImageFileModeConstants.Write);
|
|
|
- // _cogImageFileTool.Append(image);
|
|
|
- // _cogImageFileTool.Close();
|
|
|
- //}
|
|
|
+ using (CogImageFile _cogImageFileTool = new CogImageFile())
|
|
|
+ {
|
|
|
+ _cogImageFileTool.Open(Originalpath, CogImageFileModeConstants.Write);
|
|
|
+ _cogImageFileTool.Append(image);
|
|
|
+ _cogImageFileTool.Close();
|
|
|
+ }
|
|
|
|
|
|
- using (CogImageFile _cogImageFileTool = new CogImageFile())
|
|
|
- {
|
|
|
- _cogImageFileTool.Open(Originalpath, CogImageFileModeConstants.Write);
|
|
|
- _cogImageFileTool.Append(image);
|
|
|
- _cogImageFileTool.Close();
|
|
|
- }
|
|
|
+ cancellationToken.ThrowIfCancellationRequested();
|
|
|
|
|
|
- if (!Directory.Exists(Path.GetDirectoryName(Recordedpath)))
|
|
|
- Directory.CreateDirectory(Path.GetDirectoryName(Recordedpath));
|
|
|
+ if (!Directory.Exists(Path.GetDirectoryName(Recordedpath)))
|
|
|
+ Directory.CreateDirectory(Path.GetDirectoryName(Recordedpath));
|
|
|
|
|
|
- if (isCompress)
|
|
|
- {
|
|
|
- ImageHelper.CompressImage(reimage, Recordedpath, 20);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- reimage.Save(Recordedpath);
|
|
|
- }
|
|
|
+ if (isCompress)
|
|
|
+ {
|
|
|
+ ImageHelper.CompressImage(reimage, Recordedpath, 20);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ reimage.Save(Recordedpath);
|
|
|
}
|
|
|
}
|
|
|
- catch (Exception ex)
|
|
|
- {
|
|
|
- LogHelper.WriteLogError("保存流程运行结果的图片时出错!", ex);
|
|
|
- }
|
|
|
- finally
|
|
|
- {
|
|
|
- // ======================= 【关键修复】无论是否压缩都释放Bitmap =======================
|
|
|
- try { reimage?.Dispose(); } catch { }
|
|
|
- }
|
|
|
- });
|
|
|
+ }
|
|
|
+ catch (OperationCanceledException)
|
|
|
+ {
|
|
|
+ // 正常取消,不记录日志
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ LogHelper.WriteLogError("保存流程运行结果的图片时出错!", ex);
|
|
|
+ }
|
|
|
+ finally
|
|
|
+ {
|
|
|
+ try { reimage?.Dispose(); } catch { }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
private void ProductChanged(ProductModel product)
|