public bool ClearPhotoCache(string photo_path) { if (string.IsNullOrEmpty(photo_path)) { return(false); } /* * string cacheDir = Path.Combine(WpfClientInfo.UserDir, "photo"); * string fileName = Path.Combine(cacheDir, GetPath(photo_path)); */ string fileName = GetCachePhotoPath(photo_path); try { SetPhoto((Stream)null); if (File.Exists(fileName)) { File.Delete(fileName); return(true); } return(false); } catch (Exception ex) { WpfClientInfo.WriteErrorLog($"清除照片缓存文件 '{fileName}' 时出现异常: {ExceptionUtil.GetDebugText(ex)}"); return(false); } }
// 开始监控一个门 public void BeginMonitor(DoorItem door) { lock (_syncRoot) { // 检查以前这个门是否已经有监控消息 var message = _messages.Find((m) => { if (m.Door == door) { return(true); } return(false); }); if (message != null) { App.CurrentApp.Speak("补做遗留提交"); WpfClientInfo.WriteInfoLog($"对门 {message.Door.Name} 补做一次 submit (1)"); _func_submit?.Invoke(message.Door, false); message.StartTime = DateTime.Now; // 重新开始 message.HeartbeatTicks = RfidManager.LockHeartbeat; } else { message = new MonitorMessage { Door = door, StartTime = DateTime.Now, HeartbeatTicks = RfidManager.LockHeartbeat }; _messages.Add(message); } } }
// 处理一次监控任务 public void ProcessTimeout() { lock (_syncRoot) { List <MonitorMessage> delete_messages = new List <MonitorMessage>(); foreach (var message in _messages) { // if (DateTime.Now - message.StartTime > TimeoutLength) if (RfidManager.LockHeartbeat - message.HeartbeatTicks >= 2) { App.CurrentApp.Speak("超时补做提交"); WpfClientInfo.WriteInfoLog($"超时情况下,对门 {message.Door.Name} 补做一次 submit"); _func_submit?.Invoke(message.Door, true); delete_messages.Add(message); message.Door.Waiting--; } } foreach (var message in delete_messages) { _messages.Remove(message); } } }
// 新版本的事件 #pragma warning disable VSTHRD100 // 避免使用 Async Void 方法 private async void CurrentApp_NewTagChanged(object sender, NewTagChangedEventArgs e) #pragma warning restore VSTHRD100 // 避免使用 Async Void 方法 { try { // throw new Exception("testing"); var channel = (BaseChannel <IRfid>)sender; // TODO: 对离开的 tag 变化为灰色颜色 bool speaked = false; // 2020/10/10 // TODO: 发出什么响声表示? // 把以前遗留的出错 entity 尝试重新 GetTagInfo() foreach (var entity in InventoryData.ErrorEntities) { FillEntity(channel, entity, (e1) => { // 说过一次便不再说 if (speaked == true) { return(false); } speaked = SpeakLocation(e1); return(speaked); }); } // 筛选出需要 GetTagInfo() 的那些标签 await FilterTags(channel, e.AddTags); #if NO SoundMaker.InitialSequence(e.AddTags.Count); foreach (var tag in e.AddTags) { SoundMaker.NextSound(); ProcessTag(channel, tag); } SoundMaker.StopCurrent(); #endif /* * foreach (var tag in e.UpdateTags) * { * ProcessTag(channel, tag); * } */ App.SetError("NewTagChanged", null); } catch (Exception ex) { App.SetError("NewTagChanged", $"CurrentApp_NewTagChanged() 捕获异常: {ex.Message}"); WpfClientInfo.WriteErrorLog($"CurrentApp_NewTagChanged() 捕获异常: {ExceptionUtil.GetDebugText(ex)}"); } }
protected override void OnExit(ExitEventArgs e) { this._channelPool.BeforeLogin -= new DigitalPlatform.LibraryClient.BeforeLoginEventHandle(Channel_BeforeLogin); this._channelPool.AfterLogin -= new AfterLoginEventHandle(Channel_AfterLogin); this._channelPool.Close(); WpfClientInfo.Finish(); base.OnExit(e); }
private void PageInventory_Loaded(object sender, RoutedEventArgs e) { App.NewTagChanged += CurrentApp_NewTagChanged; App.IsPageInventoryActive = true; _ = Task.Run(() => { CancellationTokenSource cancel = new CancellationTokenSource(); ProgressWindow progress = null; App.Invoke(new Action(() => { progress = new ProgressWindow(); progress.TitleText = "dp2SSL -- 盘点"; progress.MessageText = "正在获取 UID 对照信息,请稍候 ..."; progress.Owner = Application.Current.MainWindow; progress.WindowStartupLocation = WindowStartupLocation.CenterOwner; progress.Closed += (s, e1) => { cancel.Cancel(); }; progress.okButton.Visibility = Visibility.Collapsed; // progress.okButton.Content = "停止"; App.SetSize(progress, "middle"); progress.BackColor = "green"; progress.Show(); })); try { Hashtable uid_table = new Hashtable(); var result = InventoryData.DownloadUidTable( null, uid_table, (text) => { App.Invoke(new Action(() => { progress.MessageText = text; })); }, cancel.Token); InventoryData.SetUidTable(uid_table); } catch (Exception ex) { WpfClientInfo.WriteErrorLog($"准备册记录过程出现异常: {ExceptionUtil.GetDebugText(ex)}"); } finally { App.Invoke(new Action(() => { progress.Close(); })); } }); }
private void openKeyboard_Click(object sender, RoutedEventArgs e) { try { Process.Start("osk"); } catch (Exception ex) { WpfClientInfo.WriteErrorLog($"打开触摸键盘时出现异常: {ExceptionUtil.GetDebugText(ex)}"); } }
public static async Task <NormalResult> RenewAsync(string patronBarcode, string itemBarcode) { try { using (var releaser = await _channelLimit.EnterAsync()) { SipChannel channel = await GetChannelAsync(); try { var result = await channel.RenewAsync(patronBarcode, itemBarcode); if (result.Value == -1) { return new NormalResult { Value = -1, ErrorInfo = result.ErrorInfo, ErrorCode = result.ErrorCode } } ; if (result.Value == 0) { return new NormalResult { Value = -1, ErrorInfo = result.ErrorInfo, ErrorCode = result.ErrorCode } } ; return(new NormalResult()); } finally { ReturnChannel(channel); } } } catch (Exception ex) { WpfClientInfo.WriteErrorLog($"RenewAsync() 出现异常: {ExceptionUtil.GetDebugText(ex)}"); return(new GetEntityDataResult { Value = -1, ErrorInfo = $"RenewAsync() 出现异常: {ex.Message}", ErrorCode = ex.GetType().ToString() }); } }
// 把 Actions 追加保存到本地数据库 // 当本函数执行完以后,ActionInfo 对象的 ID 有了值,和数据库记录的 ID 对应 public static async Task SaveActionsToDatabaseAsync(List <ActionInfo> actions) { try { using (var releaser = await _databaseLimit.EnterAsync()) { using (var context = new RequestContext()) { context.Database.EnsureCreated(); var requests = FromActions(actions); foreach (var request in requests) { // 注:这样一个一个保存可以保持 ID 的严格从小到大。因为这些事项之间是有严格顺序关系的(借和还顺序不能颠倒) await context.Requests.AddRangeAsync(request); int nCount = await context.SaveChangesAsync(); // 2020/4/27 // 如果是还书动作,需要更新它之前的全部同 PII 的借书动作的 LinkID 字段 if (request.Action == "return" || request.Action == "inventory") { var borrowRequests = context.Requests. Where(o => o.PII == request.PII && o.Action == "borrow" && o.LinkID == null) .ToList(); foreach (var item in borrowRequests) { item.LinkID = request.ID.ToString(); context.Requests.Update(item); await context.SaveChangesAsync(); } } } Debug.Assert(requests.Count == actions.Count, ""); // 刷新 ActionInfo 对象的 ID for (int i = 0; i < requests.Count; i++) { actions[i].ID = requests[i].ID; } WpfClientInfo.WriteInfoLog($"Actions 保存到本地数据库成功。内容如下:\r\n{ActionInfo.ToString(actions)}"); } } } catch (Exception ex) { WpfClientInfo.WriteErrorLog($"SaveActionsToDatabase() 出现异常: {ExceptionUtil.GetDebugText(ex)}"); throw ex; } }
// sync/commerror/normalerror/空 // 同步成功/通讯出错/一般出错/从未同步过 // 从外部存储中装载尚未同步的 Actions // 注意:这些 Actions 应该先按照 PII 排序分组以后,一组一组进行处理 public static async Task <List <ActionInfo> > LoadRetryActionsFromDatabaseAsync() { using (var releaser = await _databaseLimit.EnterAsync()) { using (var context = new RequestContext()) { context.Database.EnsureCreated(); var items = context.Requests.Where(o => o.State != "sync" && o.State != "dontsync") .OrderBy(o => o.ID).ToList(); var actions = FromRequests(items); WpfClientInfo.WriteInfoLog($"从本地数据库装载 Actions 成功。内容如下:\r\n{ActionInfo.ToString(actions)}"); return(actions); } } }
// 启动盘点后台任务 public static void StartInventoryTask() { if (_inventoryTask != null) { return; } CancellationToken token = App.CancelToken; token.Register(() => { _eventInventory.Set(); }); _inventoryTask = Task.Factory.StartNew(async() => { WpfClientInfo.WriteInfoLog("盘点后台线程开始"); try { while (token.IsCancellationRequested == false) { // await Task.Delay(TimeSpan.FromSeconds(10)); _eventInventory.WaitOne(_inventoryIdleLength); token.ThrowIfCancellationRequested(); // await ProcessingAsync(); } _inventoryTask = null; } catch (OperationCanceledException) { } catch (Exception ex) { WpfClientInfo.WriteErrorLog($"盘点后台线程出现异常: {ExceptionUtil.GetDebugText(ex)}"); App.SetError("inventory_worker", $"盘点后台线程出现异常: {ex.Message}"); } finally { WpfClientInfo.WriteInfoLog("盘点后台线程结束"); } }, token, TaskCreationOptions.LongRunning, TaskScheduler.Default); }
// result.Value // 0 没有找到记录。没有发生更新 // 1 成功更新 public static async Task <NormalResult> UpdateEntityXmlAsync(string pii, string item_xml, byte[] timestamp) { try { using (BiblioCacheContext context = new BiblioCacheContext()) { if (_cacheDbCreated == false) { context.Database.EnsureCreated(); _cacheDbCreated = true; } // 先尝试从本地实体库中获得原记录 var entity_record = context.Entities.Where(o => o.PII == pii).FirstOrDefault(); if (entity_record == null) { return new NormalResult { Value = 0 } } ; entity_record.Xml = item_xml; entity_record.Timestamp = timestamp; // 保存到本地数据库 context.Entities.Update(entity_record); await context.SaveChangesAsync(); return(new NormalResult { Value = 1 }); } } catch (Exception ex) { WpfClientInfo.WriteErrorLog($"UpdateEntityXmlAsync() 出现异常: {ExceptionUtil.GetDebugText(ex)}"); return(new NormalResult { Value = -1, ErrorInfo = $"UpdateEntityXmlAsync() 出现异常: {ex.Message}" }); } }
public static void Start( List <ProcessInfo> process_infos, delegate_writeLog writeLog, CancellationToken token) { TimeSpan wait_time = TimeSpan.FromSeconds(30); Task.Run(() => { while (token.IsCancellationRequested == false) { // 延时 try { Task.Delay(// TimeSpan.FromMilliseconds(1000), wait_time, token).Wait(); } catch { return; } foreach (ProcessInfo info in process_infos) { if (token.IsCancellationRequested) { return; } if (WpfClientInfo.HasModuleStarted(info.MutexName) == true) { continue; } // TODO: 写入日志 writeLog?.Invoke(info, "进程被重新启动"); // 启动 WpfClientInfo.StartModule(info.ShortcutPath, "minimize"); } } }); }
protected override void OnStartup(StartupEventArgs e) { if (DetectVirus.Detect360() || DetectVirus.DetectGuanjia()) { MessageBox.Show("dp2SSL 被木马软件干扰,无法启动"); System.Windows.Application.Current.Shutdown(); return; } WpfClientInfo.TypeOfProgram = typeof(App); if (StringUtil.IsDevelopMode() == false) { WpfClientInfo.PrepareCatchException(); } WpfClientInfo.Initial("dp2SSL"); base.OnStartup(e); this._channelPool.BeforeLogin += new DigitalPlatform.LibraryClient.BeforeLoginEventHandle(Channel_BeforeLogin); this._channelPool.AfterLogin += new AfterLoginEventHandle(Channel_AfterLogin); // 后台自动检查更新 Task.Run(() => { NormalResult result = WpfClientInfo.InstallUpdateSync(); if (result.Value == -1) { OutputHistory("自动更新出错: " + result.ErrorInfo, 2); } else if (result.Value == 1) { OutputHistory(result.ErrorInfo, 1); } else if (string.IsNullOrEmpty(result.ErrorInfo) == false) { OutputHistory(result.ErrorInfo, 0); } }); }
// 2020/8/26 // 把本地动作库中符合指定 borrowID 的状态修改为 “dontsync” internal static async Task ChangeDatabaseBorrowStateAsync(string borrowID) { using (var releaser = await _databaseLimit.EnterAsync()) { using (var context = new RequestContext()) { var items = context.Requests.Where(o => o.Action == "borrow" && o.LinkID == null && string.IsNullOrEmpty(o.ActionString) == false).ToList(); RequestItem request = null; foreach (var item in items) { try { var borrow_info = JsonConvert.DeserializeObject <BorrowInfo>(item.ActionString); if (borrow_info.BorrowID == borrowID) { request = item; break; } } catch (Exception ex) { WpfClientInfo.WriteErrorLog($"解析 borrow_info 字符串 '{item.ActionString}' 时出现异常: {ExceptionUtil.GetDebugText(ex)}"); } } if (request != null) { // request.State = "dontsync"; // 表示这个借书动作已经发生了还书 request.LinkID = $"borrowID={borrowID}"; context.SaveChanges(); } } } }
public static bool ClearPhotoCacheFile(string photo_path) { if (string.IsNullOrEmpty(photo_path)) { return(false); } string fileName = GetCachePhotoPath(photo_path); try { if (File.Exists(fileName)) { File.Delete(fileName); return(true); } return(false); } catch (Exception ex) { WpfClientInfo.WriteErrorLog($"删除照片缓存文件 '{fileName}' 时出现异常: {ExceptionUtil.GetDebugText(ex)}"); return(false); } }
// 将指定门的暂存的信息保存为 Action。但并不立即提交 public async static Task SaveDoorActions(DoorItem door, bool clearOperator) { var result = await ShelfData.SaveActions((entity) => { var results = DoorItem.FindDoors(ShelfData.Doors, entity.ReaderName, entity.Antenna); // TODO: 如果遇到 results.Count > 1 是否抛出异常? if (results.Count > 1) { WpfClientInfo.WriteErrorLog($"读卡器名 '{entity.ReaderName}' 天线编号 {entity.Antenna} 匹配上 {results.Count} 个门"); throw new Exception($"读卡器名 '{entity.ReaderName}' 天线编号 {entity.Antenna} 匹配上 {results.Count} 个门。请检查 shelf.xml 并修正配置此错误,确保只匹配一个门"); } if (results.IndexOf(door) != -1) { return(door.Operator); // return GetOperator(entity); } return(null); }); if (result.Value == -1) { SetGlobalError("save_actions", $"SaveDoorActions() 出错: {result.ErrorInfo}"); PageShelf.TrySetMessage(null, $"SaveDoorActions() 出错: {result.ErrorInfo}。这是一个严重错误,请管理员及时介入处理"); } else { SetGlobalError("save_actions", null); } // 2019/12/21 if (clearOperator == true && door.State == "close") { door.Operator = null; // 清掉门上的操作者名字 } }
// 启动同步任务。此任务长期在后台运行 public static void StartSyncTask() { if (_syncTask != null) { return; } CancellationToken token = _cancel.Token; token.Register(() => { _eventSync.Set(); }); // 启动重试专用线程 _syncTask = Task.Factory.StartNew(async() => { WpfClientInfo.WriteInfoLog("重试专用线程开始"); try { while (token.IsCancellationRequested == false) { // TODO: 无论是整体退出,还是需要激活,都需要能中断 Delay // Task.Delay(TimeSpan.FromSeconds(10)).Wait(token); _eventSync.WaitOne(_syncIdleLength); token.ThrowIfCancellationRequested(); #if REMOVED // 顺便检查和确保连接到消息服务器 App.CurrentApp.EnsureConnectMessageServer().Wait(token); #endif #if REMOVED // 顺便关闭天线射频 if (_tagAdded) { _ = Task.Run(async() => { try { await SelectAntennaAsync(); } catch { // TODO: 写入错误日志 } }); _tagAdded = false; } #endif if (PauseSubmit) { continue; } // 2020/6/21 if (ShelfData.LibraryNetworkCondition != "OK") { continue; } // TODO: 从本地数据库中装载需要同步的那些 Actions List <ActionInfo> actions = await LoadRetryActionsFromDatabaseAsync(); if (actions.Count == 0) { continue; } // RefreshRetryInfo() ??? // 一般来说,只要 SubmitWindow 开着,就要显示请求情况结果。 // 特殊地,如果 SubmitWindow 没有开着,但本次至少有一个成功的请求结果了,那就专门打开 SubmitWindow 显示信息 int succeedCount = 0; // 同步成功的事项数量 int newCount = 0; // 首次进行同步的事项数量 // 排序和分组。按照分组提交给 dp2library 服务器 // TODO: 但进度显示不应该太细碎?应该按照总的进度来显示 var groups = GroupActions(actions); // List<MessageItem> messages = new List<MessageItem>(); // 准备对话框 // SubmitWindow progress = PageMenu.PageShelf?.OpenProgressWindow(); SubmitWindow progress = PageMenu.PageShelf?.ProgressWindow; int start = 0; // 当前 group 开始的偏移 int total = actions.Count; foreach (var group in groups) { int current_count = group.Count; // 当前 group 包含的动作数量 var result = await SubmitCheckInOutAsync( (min, max, value, text) => { // 2020/4/2 // 修正三个值 if (max != -1) { max = total; } //if (min != -1) // min += start; if (value != -1) { value += start; } if (progress != null) { App.Invoke(new Action(() => { if (min == -1 && max == -1 && value == -1 && groups.IndexOf(group) == groups.Count - 1) // 只有最后一次才隐藏进度条 { progress.ProgressBar.Visibility = Visibility.Collapsed; } else { progress.ProgressBar.Visibility = Visibility.Visible; } if (text != null) { progress.TitleText = text; // + " " + (progress.Tag as string); } if (min != -1) { progress.ProgressBar.Minimum = min; } if (max != -1) { progress.ProgressBar.Maximum = max; } if (value != -1) { progress.ProgressBar.Value = value; } })); } }, group, "auto_stop"); // TODO: 把 group 中报错的信息写入本地数据库的对应事项中 /* * // 把已经处理成功的 Action 对应在本地数据库中的事项的状态修改 * List<ActionInfo> processed = new List<ActionInfo>(); * if (result.RetryActions != null) * { * foreach (var action in group) * { * if (result.RetryActions.IndexOf(action) == -1) * { * ChangeDatabaseActionState(action.ID, "sync"); * processed.Add(action); * } * } * } */ if (result.ProcessedActions != null) { // result.ProcessedActions.ForEach(o => { if (o.SyncCount == 0) newCount++; }); foreach (var action in result.ProcessedActions) { if (action.State == "sync") { succeedCount++; } if (action.SyncCount == 1) { newCount++; } // sync/commerror/normalerror/空 // 同步成功/通讯出错/一般出错/从未同步过 await ChangeDatabaseActionStateAsync(action.ID, action); } // TODO: 通知消息正文是否也告知一下同一个 PII 后面有多少个动作被跳过处理? MessageNotifyOverflow(result.ProcessedActions); } if (progress != null && progress.IsVisible) { // 根据全部和已处理集合得到未处理(被跳过的)集合 var skipped = GetSkippedActions(group, result.ProcessedActions); foreach (var action in skipped) { action.State = "_"; action.SyncErrorCode = "skipped"; // action.SyncErrorInfo = "暂时跳过同步"; } List <ActionInfo> display = new List <ActionInfo>(result.ProcessedActions); display.AddRange(skipped); // Thread.Sleep(3000); // 刷新显示 App.Invoke(new Action(() => { progress?.Refresh(display); })); } /* * if (result.MessageDocument != null) * messages.AddRange(result.MessageDocument.Items); */ start += current_count; } // TODO: 更新每个事项的 RetryCount。如果超过 10 次,要把 State 更新为 fail // 将 submit 情况写入日志备查 // WpfClientInfo.WriteInfoLog($"重试提交请求:\r\n{ActionInfo.ToString(actions)}\r\n返回结果:{result.ToString()}"); #if REMOVED // 如果本轮有成功的请求,并且进度窗口没有打开,则补充打开进度窗口 if ((progress == null || progress.IsVisible == false) && succeedCount > 0) { progress = PageMenu.PageShelf?.OpenProgressWindow(); } // 把执行结果显示到对话框内 // 全部事项都重试失败的时候不需要显示 if (progress != null && progress.IsVisible && (succeedCount > 0 || newCount > 0)) { Application.Current.Dispatcher.Invoke(new Action(() => { MessageDocument doc = new MessageDocument(); doc.AddRange(messages); progress?.PushContent(doc); })); // 显示出来 Application.Current.Dispatcher.Invoke(new Action(() => { progress?.ShowContent(); })); } #endif } _syncTask = null; } catch (OperationCanceledException) { } catch (Exception ex) { WpfClientInfo.WriteErrorLog($"重试专用线程出现异常: {ExceptionUtil.GetDebugText(ex)}"); App.SetError("sync", $"重试专用线程出现异常: {ex.Message}"); } finally { WpfClientInfo.WriteInfoLog("重试专用线程结束"); } }, token, TaskCreationOptions.LongRunning, TaskScheduler.Default); }
private void PageInventory_Loaded(object sender, RoutedEventArgs e) { App.NewTagChanged += CurrentApp_NewTagChanged; App.IsPageInventoryActive = true; RefreshActionModeMenu(); _ = Task.Run(() => { // 获得馆藏地列表 GetLocationListResult get_result = LibraryChannelUtil.GetLocationList(); if (get_result.Value == -1) { App.SetError("inventory", $"获得馆藏地列表时出错: {get_result.ErrorInfo}"); } string batchNo = "inventory_" + DateTime.Now.ToShortDateString(); bool slow_mode = false; bool dialog_result = false; // “开始盘点”对话框 App.Invoke(new Action(() => { App.PauseBarcodeScan(); try { BeginInventoryWindow dialog = new BeginInventoryWindow(); dialog.TitleText = $"开始盘点"; // dialog.Text = $"如何处理以上放入 {door_names} 的 {collection.Count} 册图书?"; dialog.Owner = App.CurrentApp.MainWindow; // dialog.BatchNo = batchNo; dialog.WindowStartupLocation = WindowStartupLocation.CenterOwner; App.SetSize(dialog, "tall"); dialog.location.ItemsSource = get_result.List; // result.List; dialog.BatchNo = batchNo; dialog.ActionMode = ActionMode; dialog.ShowDialog(); if (dialog.DialogResult == false) { dialog_result = false; } else { dialog_result = true; { _actionMode = dialog.ActionMode; RefreshActionModeMenu(); } CurrentLocation = dialog.Location; CurrentBatchNo = dialog.BatchNo; slow_mode = dialog.SlowMode; } } finally { App.ContinueBarcodeScan(); } })); ClearList(); if (dialog_result == true && slow_mode == false) { CancellationTokenSource cancel = new CancellationTokenSource(); ProgressWindow progress = null; App.Invoke(new Action(() => { progress = new ProgressWindow(); progress.TitleText = "dp2SSL -- 盘点"; progress.MessageText = "正在获取 UID 对照信息,请稍候 ..."; progress.Owner = Application.Current.MainWindow; progress.WindowStartupLocation = WindowStartupLocation.CenterOwner; progress.Closed += (s, e1) => { cancel.Cancel(); }; progress.okButton.Visibility = Visibility.Collapsed; // progress.okButton.Content = "停止"; App.SetSize(progress, "middle"); progress.BackColor = "green"; progress.Show(); })); try { Hashtable uid_table = new Hashtable(); var result = InventoryData.DownloadUidTable( null, uid_table, (text) => { App.Invoke(new Action(() => { progress.MessageText = text; })); }, cancel.Token); InventoryData.SetUidTable(uid_table); } catch (Exception ex) { WpfClientInfo.WriteErrorLog($"准备册记录过程出现异常: {ExceptionUtil.GetDebugText(ex)}"); } finally { App.Invoke(new Action(() => { progress.Close(); })); } } }); }
// 启动一般监控任务 public static void StartMonitorTask() { if (_monitorTask != null) { return; } PerdayTask.StartPerdayTask(); CancellationToken token = _cancel.Token; // bool download_complete = false; token.Register(() => { _eventMonitor.Set(); }); _monitorTask = Task.Factory.StartNew(async() => { WpfClientInfo.WriteInfoLog("书柜监控专用线程开始"); try { while (token.IsCancellationRequested == false) { // await Task.Delay(TimeSpan.FromSeconds(10)); _eventMonitor.WaitOne(_monitorIdleLength); token.ThrowIfCancellationRequested(); // *** // 关闭天线射频 if (_tagAdded) { _ = Task.Run(async() => { try { await SelectAntennaAsync(); } catch (Exception ex) { WpfClientInfo.WriteErrorLog($"关闭天线射频 SelectAntennaAsync() 时出现异常: {ExceptionUtil.GetDebugText(ex)}"); } }); _tagAdded = false; } if (DateTime.Now - _lastDetectTime > _detectPeriod) { DetectLibraryNetwork(); _lastDetectTime = DateTime.Now; } // 提醒关门 WarningCloseDoor(); // 下载或同步读者信息 string startDate = LoadStartDate(); if (/*download_complete == false || */ string.IsNullOrEmpty(startDate) && _replicatePatronError == 0) { // 如果 Config 中没有记载断点位置,说明以前从来没有首次同步过。需要进行一次首次同步 if (string.IsNullOrEmpty(startDate)) { // SaveStartDate(""); var repl_result = await PatronReplication.DownloadAllPatronRecordAsync( (text) => { WpfClientInfo.WriteInfoLog(text); PageShelf.TrySetMessage(null, text); }, token); if (repl_result.Value == -1) { // TODO: 判断通讯出错的错误码。如果是通讯出错,则稍后需要重试下载 _replicatePatronError++; } else { SaveStartDate(repl_result.StartDate); } // 立刻允许接着做一次零星同步 ActivateMonitor(); } // download_complete = true; } else { // 进行零星同步 if (DateTime.Now - _lastReplicateTime > _replicatePeriod) { // string startDate = LoadStartDate(); // testing // startDate = "20200507:0-"; if (string.IsNullOrEmpty(startDate) == false) { string endDate = DateTimeUtil.DateTimeToString8(DateTime.Now); // parameters: // strLastDate 处理中断或者结束时返回最后处理过的日期 // last_index 处理或中断返回时最后处理过的位置。以后继续处理的时候可以从这个偏移开始 // return: // -1 出错 // 0 中断 // 1 完成 ReplicationResult repl_result = await PatronReplication.DoReplication( startDate, endDate, LogType.OperLog, token); if (repl_result.Value == -1) { WpfClientInfo.WriteErrorLog($"同步出错: {repl_result.ErrorInfo}"); } else if (repl_result.Value == 1) { string lastDate = repl_result.LastDate + ":" + repl_result.LastIndex + "-"; // 注意 - 符号不能少。少了意思就会变成每次只获取一条日志记录了 SaveStartDate(lastDate); } _lastReplicateTime = DateTime.Now; } } } } _monitorTask = null; } catch (OperationCanceledException) { } catch (Exception ex) { WpfClientInfo.WriteErrorLog($"书柜监控专用线程出现异常: {ExceptionUtil.GetDebugText(ex)}"); App.SetError("shelf_monitor", $"书柜监控专用线程出现异常: {ex.Message}"); } finally { WpfClientInfo.WriteInfoLog("书柜监控专用线程结束"); } }, token, TaskCreationOptions.LongRunning, TaskScheduler.Default); }
public static void WriteInfoLog(string text) { WpfClientInfo.WriteInfoLog(text); }
// 启动一般监控任务 public static void StartMonitorTask() { if (_monitorTask != null) { return; } CancellationToken token = _cancel.Token; bool download_complete = false; token.Register(() => { _eventMonitor.Set(); }); _monitorTask = Task.Factory.StartNew(async() => { WpfClientInfo.WriteInfoLog("监控专用线程开始"); try { while (token.IsCancellationRequested == false) { // await Task.Delay(TimeSpan.FromSeconds(10)); _eventMonitor.WaitOne(_monitorIdleLength); token.ThrowIfCancellationRequested(); // *** // 关闭天线射频 if (_tagAdded) { _ = Task.Run(async() => { try { await SelectAntennaAsync(); } catch (Exception ex) { WpfClientInfo.WriteErrorLog($"关闭天线射频 SelectAntennaAsync() 时出现异常: {ExceptionUtil.GetDebugText(ex)}"); } }); _tagAdded = false; } if (DateTime.Now - _lastDetectTime > _detectPeriod) { DetectLibraryNetwork(); _lastDetectTime = DateTime.Now; } // 提醒关门 WarningCloseDoor(); // 下载或同步读者信息 string startDate = LoadStartDate(); if (/*download_complete == false || */ string.IsNullOrEmpty(startDate)) { // 如果 Config 中没有记载断点位置,说明以前从来没有首次同步过。需要进行一次首次同步 if (string.IsNullOrEmpty(startDate)) { // SaveStartDate(""); var repl_result = await PatronReplication.DownloadAllPatronRecordAsync(token); if (repl_result.Value == -1) { // TODO: 判断通讯出错的错误码。如果是通讯出错,则稍后需要重试下载 } else { SaveStartDate(repl_result.StartDate); } // 立刻允许接着做一次零星同步 ActivateMonitor(); } // download_complete = true; } else { // 进行零星同步 if (DateTime.Now - _lastReplicateTime > _replicatePeriod) { // string startDate = LoadStartDate(); // testing // startDate = "20200507:0-"; if (string.IsNullOrEmpty(startDate) == false) { string endDate = DateTimeUtil.DateTimeToString8(DateTime.Now); // parameters: // strLastDate 处理中断或者结束时返回最后处理过的日期 // last_index 处理或中断返回时最后处理过的位置。以后继续处理的时候可以从这个偏移开始 // return: // -1 出错 // 0 中断 // 1 完成 ReplicationResult repl_result = PatronReplication.DoReplication( startDate, endDate, LogType.OperLog, token); if (repl_result.Value == -1) { WpfClientInfo.WriteErrorLog($"同步出错: {repl_result.ErrorInfo}"); } else if (repl_result.Value == 1) { string lastDate = repl_result.LastDate + ":" + repl_result.LastIndex + "-"; // 注意 - 符号不能少。少了意思就会变成每次只获取一条日志记录了 SaveStartDate(lastDate); } _lastReplicateTime = DateTime.Now; } } } // 检查升级 dp2ssl if (_updated == false // && StringUtil.IsDevelopMode() == false && ApplicationDeployment.IsNetworkDeployed == false && DateTime.Now - _lastUpdateTime > _updatePeriod) { WpfClientInfo.WriteInfoLog("开始自动检查升级"); // result.Value: // -1 出错 // 0 经过检查发现没有必要升级 // 1 成功 // 2 成功,但需要立即重新启动计算机才能让复制的文件生效 var update_result = await GreenInstaller.InstallFromWeb("http://dp2003.com/dp2ssl/v1_dev", "c:\\dp2ssl", "delayExtract,updateGreenSetupExe", //true, //true, token, null); if (update_result.Value == -1) { WpfClientInfo.WriteErrorLog($"自动检查升级出错: {update_result.ErrorInfo}"); } else { WpfClientInfo.WriteInfoLog($"结束自动检查升级 update_result:{update_result.ToString()}"); } if (update_result.Value == 1 || update_result.Value == 2) { App.TriggerUpdated("重启可使用新版本"); _updated = true; PageShelf.TrySetMessage(null, "dp2SSL 升级文件已经下载成功,下次重启时可自动升级到新版本"); } _lastUpdateTime = DateTime.Now; } } _monitorTask = null; } catch (OperationCanceledException) { } catch (Exception ex) { WpfClientInfo.WriteErrorLog($"监控专用线程出现异常: {ExceptionUtil.GetDebugText(ex)}"); App.SetError("monitor", $"监控专用线程出现异常: {ex.Message}"); } finally { WpfClientInfo.WriteInfoLog("监控专用线程结束"); } }, token, TaskCreationOptions.LongRunning, TaskScheduler.Default); }
// 从 _entityList 中取出一批事项进行处理。由于是复制出来处理的,所以整个处理过程中(除了取出和最后删除的瞬间)不用对 _entityList 加锁 // 对每一个事项,要进行如下处理: // 1) 获得册记录和书目摘要 // 2) 尝试请求还书 // 3) 请求设置 UID // 4) 修改 currentLocation 和 location static async Task ProcessingAsync() { var list = CopyList(); foreach (var state in list) { // state.State = "???"; try { if (state.NewState == "open") { continue; } Debug.Assert(state.NewState == "close"); List <ActionInfo> actions = null; try { DateTime start = DateTime.Now; var result = await ShelfData.RefreshInventoryAsync(state.Door); WpfClientInfo.WriteInfoLog($"针对门 {state.Door.Name} 执行 RefreshInventoryAsync() 耗时 {(DateTime.Now - start).TotalSeconds.ToString()}"); start = DateTime.Now; // 2020/4/21 把这两句移动到 try 范围内 await SaveDoorActions(state.Door, true); WpfClientInfo.WriteInfoLog($"针对门 {state.Door.Name} 执行 SaveDoorActions() 耗时 {(DateTime.Now - start).TotalSeconds.ToString()}"); start = DateTime.Now; actions = ShelfData.PullActions(); WpfClientInfo.WriteInfoLog($"针对门 {state.Door.Name} 执行 PullActions() 耗时 {(DateTime.Now - start).TotalSeconds.ToString()}"); } finally { state.Door.DecWaiting(); //WpfClientInfo.WriteInfoLog($"--decWaiting() door '{e.Door.Name}' state changed"); } // 注: 调用完成后门控件上的 +- 数字才会消失 var task = PageMenu.PageShelf.DoRequestAsync(actions, ""); App.SetError("processing", null); } catch (Exception ex) { WpfClientInfo.WriteErrorLog($"ProcessingAsync() 出现异常: {ExceptionUtil.GetDebugText(ex)}"); App.SetError("processing", $"ProcessingAsync() 出现异常: {ex.Message}"); } finally { // state.State = ""; } } // 把处理过的 entity 从 list 中移走 RemoveList(list); // 2020/11/21 // 如果发现队列里面又有新的对象,则立即激活任务 if (GetListCount() > 0) { ActivateTask(); } }
// 启动一般监控任务 public static void StartMonitorTask() { if (_monitorTask != null) { return; } CancellationToken token = App.CancelToken; token.Register(() => { _eventMonitor.Set(); }); _monitorTask = Task.Factory.StartNew(async() => { WpfClientInfo.WriteInfoLog("SIP 监控专用线程开始"); try { while (token.IsCancellationRequested == false) { // await Task.Delay(TimeSpan.FromSeconds(10)); _eventMonitor.WaitOne(_monitorIdleLength); token.ThrowIfCancellationRequested(); if (DateTime.Now - _lastDetectTime > _detectPeriod) { var detect_result = await DetectSipNetworkAsync(); _lastDetectTime = DateTime.Now; // testing //detect_result.Value = -1; //detect_result.ErrorInfo = "测试文字"; if (detect_result.Value != 1) { App.OpenErrorWindow(detect_result.ErrorInfo); } else { App.CloseErrorWindow(); } } } _monitorTask = null; } catch (OperationCanceledException) { } catch (Exception ex) { WpfClientInfo.WriteErrorLog($"SIP 监控专用线程出现异常: {ExceptionUtil.GetDebugText(ex)}"); App.SetError("monitor", $"SIP 监控专用线程出现异常: {ex.Message}"); } finally { WpfClientInfo.WriteInfoLog("SIP 监控专用线程结束"); } }, token, TaskCreationOptions.LongRunning, TaskScheduler.Default); }
static async Task <NormalResult> DetectSipNetworkAsync() { /* * // testing * return new NormalResult { Value = 1 }; */ try { using (var releaser = await _channelLimit.EnterAsync()) { SipChannel channel = await GetChannelAsync(); try { // -1出错,0不在线,1正常 var result = await channel.ScStatusAsync(); if (result.Value == -1) { return new NormalResult { Value = -1, ErrorInfo = result.ErrorInfo, ErrorCode = result.ErrorCode } } ; if (result.Value == 0) { return new NormalResult { Value = 0, ErrorInfo = result.ErrorInfo, ErrorCode = result.ErrorCode } } ; return(new NormalResult { Value = result.Value, ErrorInfo = result.ErrorInfo, ErrorCode = result.ErrorCode }); } finally { ReturnChannel(channel); } } } catch (Exception ex) { WpfClientInfo.WriteErrorLog($"DetectSipNetworkAsync() 出现异常: {ExceptionUtil.GetDebugText(ex)}"); return(new GetEntityDataResult { Value = -1, ErrorInfo = $"DetectSipNetworkAsync() 出现异常: {ex.Message}", ErrorCode = ex.GetType().ToString() }); } }
// return.Value: // -1 出错 // 0 读者记录没有找到 // 1 成功 public static async Task <GetReaderInfoResult> GetReaderInfoAsync(string pii) { try { using (var releaser = await _channelLimit.EnterAsync()) { SipChannel channel = await GetChannelAsync(); try { List <NormalResult> errors = new List <NormalResult>(); int nRedoCount = 0; REDO_GETITEMINFO: var get_result = await _channel.GetPatronInfoAsync(pii); if (get_result.Value == -1) { return new GetReaderInfoResult { Value = -1, ErrorInfo = get_result.ErrorInfo, ErrorCode = get_result.ErrorCode } } ; /* * else if (get_result.Result.CirculationStatus_2 == "01") * { * errors.Add(new NormalResult * { * Value = -1, * ErrorInfo = get_result.Result.AF_ScreenMessage_o, * ErrorCode = get_result.Result.CirculationStatus_2 * }); * } * else if (get_result.Result.CirculationStatus_2 == "13") * { * errors.Add(new NormalResult * { * Value = -1, * ErrorInfo = get_result.Result.AF_ScreenMessage_o, * ErrorCode = "itemNotFound" * }); * } */ else { XmlDocument readerdom = new XmlDocument(); readerdom.LoadXml("<root />"); // 证状态 string state = "***"; if (get_result.Result.BL_ValidPatron_o == "Y") { state = ""; } DomUtil.SetElementText(readerdom.DocumentElement, "state", state); // 读者证条码号 DomUtil.SetElementText(readerdom.DocumentElement, "barcode", get_result.Result.AA_PatronIdentifier_r); // 姓名 DomUtil.SetElementText(readerdom.DocumentElement, "name", get_result.Result.AE_PersonalName_r); // 可借册数 Patron.SetParamValue(readerdom.DocumentElement, "当前还可借", get_result.Result.BZ_HoldItemsLimit_o); Patron.SetParamValue(readerdom.DocumentElement, "可借总册数", get_result.Result.CB_ChargedItemsLimit_o); // 在借册 var root = readerdom.DocumentElement.AppendChild(readerdom.CreateElement("borrows")) as XmlElement; var items = get_result.Result.AU_ChargedItems_o; if (items != null) { foreach (var item in items) { if (item.Value == null) { continue; } var borrow = root.AppendChild(readerdom.CreateElement("borrow")) as XmlElement; borrow.SetAttribute("barcode", item.Value); } } return(new GetReaderInfoResult { Value = 1, ReaderXml = readerdom.OuterXml, RecPath = "", Timestamp = null }); } } finally { ReturnChannel(channel); } } } catch (Exception ex) { WpfClientInfo.WriteErrorLog($"GetEntGetReaderInfoAsyncityDataAsync() 出现异常: {ExceptionUtil.GetDebugText(ex)}"); return(new GetReaderInfoResult { Value = -1, ErrorInfo = $"GetReaderInfoAsync() 出现异常: {ex.Message}", ErrorCode = ex.GetType().ToString() }); } }
// 从本地数据库获得册记录信息和书目摘要信息 // .Value // 0 没有找到 // 1 找到一种 // 2 两种都找到了 public static GetEntityDataResult LocalGetEntityData(string pii) { try { using (BiblioCacheContext context = new BiblioCacheContext()) { if (_cacheDbCreated == false) { context.Database.EnsureCreated(); _cacheDbCreated = true; } GetEntityDataResult result = null; // *** // 第一步:获取册记录 // 从本地实体库中获得记录 var entity_record = context.Entities.Where(o => o.PII == pii).FirstOrDefault(); // EntityItem entity_record = null; // testing if (entity_record != null) { result = new GetEntityDataResult { Value = 1, ItemXml = entity_record.Xml, ItemRecPath = entity_record.RecPath, Title = "", } } ; // *** /// 第二步:获取书目摘要 // 从本地书目库中获取书目摘要 var item = context.BiblioSummaries.Where(o => o.PII == pii).FirstOrDefault(); if (item != null && string.IsNullOrEmpty(item.BiblioSummary) == false) { if (result == null) { result = new GetEntityDataResult(); } result.Title = item.BiblioSummary; result.Value++; } if (result == null) { return new GetEntityDataResult { Value = 0 } } ; return(result); } } catch (Exception ex) { WpfClientInfo.WriteErrorLog($"LocalGetEntityDataAsync() 出现异常: {ExceptionUtil.GetDebugText(ex)}"); return(new GetEntityDataResult { Value = -1, ErrorInfo = $"LocalGetEntityDataAsync() 出现异常: {ex.Message}", ErrorCode = ex.GetType().ToString() }); } }
// 获得册记录信息和书目摘要信息 // parameters: // style 风格。network 表示只从网络获取册记录;否则优先从本地获取,本地没有再从网络获取册记录。无论如何,书目摘要都是尽量从本地获取 // .Value // 0 没有找到 // 1 找到 public static async Task <GetEntityDataResult> GetEntityDataAsync(string pii, string style) { bool network = StringUtil.IsInList("network", style); try { using (var releaser = await _channelLimit.EnterAsync()) using (BiblioCacheContext context = new BiblioCacheContext()) { if (_cacheDbCreated == false) { context.Database.EnsureCreated(); _cacheDbCreated = true; } LibraryChannel channel = App.CurrentApp.GetChannel(); TimeSpan old_timeout = channel.Timeout; channel.Timeout = TimeSpan.FromSeconds(10); try { GetEntityDataResult result = null; List <NormalResult> errors = new List <NormalResult>(); EntityItem entity_record = null; // *** // 第一步:获取册记录 if (network == false) { // 先尝试从本地实体库中获得记录 entity_record = context.Entities.Where(o => o.PII == pii).FirstOrDefault(); // EntityItem entity_record = null; // testing } if (entity_record != null) { result = new GetEntityDataResult { Value = 1, ItemXml = entity_record.Xml, ItemRecPath = entity_record.RecPath, Title = "", } } ; else { // 再尝试从 dp2library 服务器获取 // TODO: ItemXml 和 BiblioSummary 可以考虑在本地缓存一段时间 int nRedoCount = 0; REDO_GETITEMINFO: long lRet = channel.GetItemInfo(null, "item", pii, "", "xml", out string item_xml, out string item_recpath, out byte[] timestamp, "", out _, out _, out string strError); if (lRet == -1) { if ((channel.ErrorCode == ErrorCode.RequestError || channel.ErrorCode == ErrorCode.RequestTimeOut) && nRedoCount < 2) { nRedoCount++; goto REDO_GETITEMINFO; } // TODO: 这里不着急返回,还需要尝试获得书目摘要 errors.Add(new NormalResult { Value = -1, ErrorInfo = strError, ErrorCode = channel.ErrorCode.ToString() }); /* * return new GetEntityDataResult * { * Value = -1, * ErrorInfo = strError, * ErrorCode = channel.ErrorCode.ToString() * }; */ } else { result = new GetEntityDataResult { Value = 1, ItemXml = item_xml, ItemRecPath = item_recpath, Title = "", }; // 保存到本地数据库 await AddOrUpdateAsync(context, new EntityItem { PII = pii, Xml = item_xml, RecPath = item_recpath, Timestamp = timestamp, }); #if NO context.Entities.Add(new EntityItem { PII = pii, Xml = item_xml, RecPath = item_recpath, Timestamp = timestamp, }); try { await context.SaveChangesAsync(); } catch (Exception ex) { SqliteException sqlite_exception = ex.InnerException as SqliteException; if (sqlite_exception != null && sqlite_exception.SqliteErrorCode == 19) { // PII 发生重复了 } else { throw ex; } } #endif } } // *** /// 第二步:获取书目摘要 // 先尝试从本地书目库中获取书目摘要 var item = context.BiblioSummaries.Where(o => o.PII == pii).FirstOrDefault(); if (item != null && string.IsNullOrEmpty(item.BiblioSummary) == false) { if (result == null) { result = new GetEntityDataResult(); } result.Title = item.BiblioSummary; } else { // 从 dp2library 服务器获取书目摘要 int nRedoCount = 0; REDO_GETBIBLIOSUMMARY: long lRet = channel.GetBiblioSummary( null, pii, "", // strConfirmItemRecPath, null, out _, out string strSummary, out string strError); if (lRet == -1) { if ((channel.ErrorCode == ErrorCode.RequestError || channel.ErrorCode == ErrorCode.RequestTimeOut) && nRedoCount < 2) { nRedoCount++; goto REDO_GETBIBLIOSUMMARY; } errors.Add(new NormalResult { Value = -1, ErrorInfo = strError, ErrorCode = channel.ErrorCode.ToString() }); /* * return new GetEntityDataResult * { * Value = -1, * ErrorInfo = strError, * ErrorCode = channel.ErrorCode.ToString(), * }; */ } else { strSummary = strSummary?.Replace(". -- ", "\r\n"); // .Replace("/", "\r\n"); if (result == null) { result = new GetEntityDataResult(); } result.Title = strSummary; // 存入数据库备用 if (lRet == 1 && string.IsNullOrEmpty(strSummary) == false) { try { var exist_item = context.BiblioSummaries.Where(o => o.PII == pii).FirstOrDefault(); if (exist_item != null) { if (exist_item.BiblioSummary != strSummary) { exist_item.BiblioSummary = strSummary; context.BiblioSummaries.Update(exist_item); } } else { context.BiblioSummaries.Add(new BiblioSummaryItem { PII = pii, BiblioSummary = strSummary }); } await context.SaveChangesAsync(); } catch (Exception ex) { WpfClientInfo.WriteErrorLog($"GetEntityDataAsync() 中保存 summary 时(PII 为 '{pii}')出现异常:{ExceptionUtil.GetDebugText(ex)}"); } } } /* * return new GetEntityDataResult * { * Value = (int)lRet, * ItemXml = item_xml, * ItemRecPath = item_recpath, * Title = strSummary, * ErrorInfo = strError, * ErrorCode = channel.ErrorCode.ToString() * }; */ } // 完全成功 if (result != null && errors.Count == 0) { return(result); } if (result == null) { return new GetEntityDataResult { Value = errors[0].Value, ErrorInfo = errors[0].ErrorInfo, ErrorCode = errors[0].ErrorCode } } ; result.ErrorInfo = errors[0].ErrorInfo; result.ErrorCode = errors[0].ErrorCode; return(result); } finally { channel.Timeout = old_timeout; App.CurrentApp.ReturnChannel(channel); } } } catch (Exception ex) { WpfClientInfo.WriteErrorLog($"GetEntityDataAsync() 出现异常: {ExceptionUtil.GetDebugText(ex)}"); return(new GetEntityDataResult { Value = -1, ErrorInfo = $"GetEntityDataAsync() 出现异常: {ex.Message}", ErrorCode = ex.GetType().ToString() }); } }
public void LoadPhoto(string photo_path) { if (string.IsNullOrEmpty(photo_path)) { App.Invoke(new Action(() => { this.SetPhoto(null); })); return; } // TODO: 照片可以缓存到本地。每次只需要获取 timestamp 即可。如果 timestamp 和缓存的不一致再重新获取一次 Stream stream = null; try { // 先尝试从缓存获取 string cacheDir = Path.Combine(WpfClientInfo.UserDir, "photo"); PathUtil.CreateDirIfNeed(cacheDir); string fileName = Path.Combine(cacheDir, GetPath(photo_path)); if (File.Exists(fileName)) { try { stream = File.OpenRead(fileName); } catch (Exception ex) { WpfClientInfo.WriteErrorLog($"从读者照片本地缓存文件 {fileName} 读取内容时出现异常:{ExceptionUtil.GetDebugText(ex)}"); stream = null; } } if (stream == null) { stream = new MemoryStream(); var channel = App.CurrentApp.GetChannel(); TimeSpan old_timeout = channel.Timeout; channel.Timeout = TimeSpan.FromSeconds(30); try { long lRet = channel.GetRes( null, photo_path, stream, "data,content", // strGetStyle, null, // byte [] input_timestamp, out string strMetaData, out byte[] baOutputTimeStamp, out string strOutputPath, out string strError); if (lRet == -1) { // SetGlobalError("patron", $"获取读者照片时出错: {strError}"); // return; throw new Exception($"获取读者照片(path='{photo_path}')时出错: {strError}"); } // 顺便存储到本地 { bool suceed = false; stream.Seek(0, SeekOrigin.Begin); try { using (var file = File.OpenWrite(fileName)) { StreamUtil.DumpStream(stream, file); } suceed = true; } catch (Exception ex) { WpfClientInfo.WriteErrorLog($"读者照片写入本地缓存文件 {fileName} 时出现异常:{ExceptionUtil.GetDebugText(ex)}"); } finally { if (suceed == false) { File.Delete(fileName); } } } stream.Seek(0, SeekOrigin.Begin); } finally { channel.Timeout = old_timeout; App.CurrentApp.ReturnChannel(channel); } } App.Invoke(new Action(() => { this.SetPhoto(stream); })); stream = null; } finally { if (stream != null) { stream.Dispose(); } } }
// 获得册记录信息和书目摘要信息 // parameters: // style 风格。network 表示只从网络获取册记录;否则优先从本地获取,本地没有再从网络获取册记录。无论如何,书目摘要都是尽量从本地获取 // .Value // 0 没有找到 // 1 找到 public static async Task <GetEntityDataResult> GetEntityDataAsync(string pii, string style) { bool network = StringUtil.IsInList("network", style); try { using (var releaser = await _channelLimit.EnterAsync()) { SipChannel channel = await GetChannelAsync(); try { GetEntityDataResult result = null; List <NormalResult> errors = new List <NormalResult>(); EntityItem entity_record = null; // *** // 第一步:获取册记录 { // 再尝试从 dp2library 服务器获取 // TODO: ItemXml 和 BiblioSummary 可以考虑在本地缓存一段时间 int nRedoCount = 0; REDO_GETITEMINFO: var get_result = await _channel.GetItemInfoAsync("", pii); if (get_result.Value == -1) { errors.Add(new NormalResult { Value = -1, ErrorInfo = get_result.ErrorInfo, ErrorCode = get_result.ErrorCode }); } else if (get_result.Result.CirculationStatus_2 == "01") { errors.Add(new NormalResult { Value = -1, ErrorInfo = get_result.Result.AF_ScreenMessage_o, ErrorCode = get_result.Result.CirculationStatus_2 }); } else if (get_result.Result.CirculationStatus_2 == "13") { errors.Add(new NormalResult { Value = -1, ErrorInfo = get_result.Result.AF_ScreenMessage_o, ErrorCode = "itemNotFound" }); } else { XmlDocument itemdom = new XmlDocument(); itemdom.LoadXml("<root />"); string state = ""; if (get_result.Result.CirculationStatus_2 == "12") { state = "丢失"; } DomUtil.SetElementText(itemdom.DocumentElement, "state", state); DomUtil.SetElementText(itemdom.DocumentElement, "barcode", get_result.Result.AB_ItemIdentifier_r); DomUtil.SetElementText(itemdom.DocumentElement, "location", get_result.Result.AQ_PermanentLocation_o); DomUtil.SetElementText(itemdom.DocumentElement, "currentLocation", get_result.Result.AP_CurrentLocation_o); DomUtil.SetElementText(itemdom.DocumentElement, "accessNo", get_result.Result.CH_ItemProperties_o); // 借书时间 { string borrowDateString = get_result.Result.CM_HoldPickupDate_18; if (string.IsNullOrEmpty(borrowDateString) == false) { if (DateTime.TryParseExact(borrowDateString, "yyyyMMdd HHmmss", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime borrowDate)) { DomUtil.SetElementText(itemdom.DocumentElement, "borrowDate", DateTimeUtil.Rfc1123DateTimeStringEx(borrowDate)); DomUtil.SetElementText(itemdom.DocumentElement, "borrower", "***"); } else { // 报错,时间字符串格式错误,无法解析 } } } // 应还书时间 { string returnningDateString = get_result.Result.AH_DueDate_o; if (string.IsNullOrEmpty(returnningDateString) == false) { if (DateTime.TryParseExact(returnningDateString, DateFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime returningDate)) { DomUtil.SetElementText(itemdom.DocumentElement, "returningDate", DateTimeUtil.Rfc1123DateTimeStringEx(returningDate)); } else { // 报错,时间字符串格式错误,无法解析 } } } result = new GetEntityDataResult { Value = 1, ItemXml = itemdom.OuterXml, ItemRecPath = get_result.Result.AB_ItemIdentifier_r, Title = get_result.Result.AJ_TitleIdentifier_r, }; /* * // 保存到本地数据库 * await AddOrUpdateAsync(context, new EntityItem * { * PII = pii, * Xml = item_xml, * RecPath = item_recpath, * Timestamp = timestamp, * }); */ } } // *** /// 第二步:获取书目摘要 // 完全成功 if (result != null && errors.Count == 0) { return(result); } if (result == null) { return new GetEntityDataResult { Value = errors[0].Value, ErrorInfo = errors[0].ErrorInfo, ErrorCode = errors[0].ErrorCode } } ; result.ErrorInfo = errors[0].ErrorInfo; result.ErrorCode = errors[0].ErrorCode; return(result); } finally { ReturnChannel(channel); } } } catch (Exception ex) { WpfClientInfo.WriteErrorLog($"GetEntityDataAsync() 出现异常: {ExceptionUtil.GetDebugText(ex)}"); return(new GetEntityDataResult { Value = -1, ErrorInfo = $"GetEntityDataAsync() 出现异常: {ex.Message}", ErrorCode = ex.GetType().ToString() }); } }