public async Task NoLeakForContestedRequests_ThatAreEventuallyAdmitted(int contestingNumbers) { var sem = new AsyncSemaphore(1); var releasers = new Task <AsyncSemaphore.Releaser> [contestingNumbers]; await this.CheckGCPressureAsync( async delegate { var blockingReleaser = await sem.EnterAsync(); for (int i = 0; i < releasers.Length; i++) { releasers[i] = sem.EnterAsync(); } // Now let the first one in. blockingReleaser.Dispose(); // Now dispose the first one, and each one afterward as it is let in. for (int i = 0; i < releasers.Length; i++) { (await releasers[i]).Dispose(); } }, maxBytesAllocated : -1, iterations : 5); }
public async Task CurrentCount() { const int initialCapacity = 3; var sem = new AsyncSemaphore(initialCapacity); Assert.Equal(initialCapacity, sem.CurrentCount); var releasers = new AsyncSemaphore.Releaser[initialCapacity]; for (int i = 0; i < initialCapacity; i++) { releasers[i] = await sem.EnterAsync(); Assert.Equal(initialCapacity - (i + 1), sem.CurrentCount); } // After requesting another beyond its capacity, it should still report 0. var extraReleaser = sem.EnterAsync(); Assert.Equal(0, sem.CurrentCount); for (int i = 0; i < initialCapacity; i++) { releasers[i].Dispose(); Assert.Equal(i, sem.CurrentCount); } extraReleaser.Result.Dispose(); Assert.Equal(initialCapacity, sem.CurrentCount); }
public async Task StartLoading(string title = null, bool isCancelable = false) { using (await _lock.EnterAsync()) { var currentCount = Interlocked.Increment(ref _loadingItems); if (currentCount == 1) { await RunOnUIAsync(async() => { _progressController = await ShellView.ShowChocolateyDialogAsync(title, isCancelable); _progressController.SetIndeterminate(); if (isCancelable) { _cst = new CancellationTokenSource(); _progressController.OnCanceled += dialog => { if (_cst != null) { _cst.Cancel(); } }; } Output.Clear(); IsLoading = true; NotifyPropertyChanged("IsLoading"); }); } } }
// 获得一个连接 public static async Task <OpenConnectionResult> OpenConnectionAsync(string userNameAndUrl) { using (var releaser = await _limit.EnterAsync()) { P2PConnection connection = _table[userNameAndUrl] as P2PConnection; if (connection != null) { // 尝试连接一次 if (connection.IsDisconnected == true) { await EnsureConnectMessageServerAsync( connection, userNameAndUrl); } return(new OpenConnectionResult { Value = 0, Connection = connection }); } var accounts = MessageAccountForm.GetAccounts(); var account = FindAccount(accounts, userNameAndUrl); if (account == null) { return(new OpenConnectionResult { Value = -1, ErrorInfo = $"用户名 '{userNameAndUrl}' 没有找到" }); } connection = new P2PConnection(); _table[userNameAndUrl] = connection; var result = await connection.ConnectAsync(account.ServerUrl, account.UserName, account.Password, ""); if (result.Value == -1) { return new OpenConnectionResult { Value = -1, ErrorInfo = result.ErrorInfo, ErrorCode = result.ErrorCode } } ; return(new OpenConnectionResult { Value = 0, Connection = connection }); } }
public static async Task LoadKeeperAsync() { await Task.Run(async() => { using (await semaphoreSlim.EnterAsync()) { PasswordKeeper = await DataLoader.LoadFromFileAsync(await GetPwdFileAsync(), Password); } }); }
public async Task EnsureCreatedAsync() { using (var releaser = await _databaseLimit.EnterAsync()) { using (var context = new QueueContext(_databaseFileName)) { context.Database.EnsureCreated(); } } }
public void TwoResourceSemaphore() { var sem = new AsyncSemaphore(2); var first = sem.EnterAsync(); var second = sem.EnterAsync(); var third = sem.EnterAsync(); Assert.Equal(TaskStatus.RanToCompletion, first.Status); Assert.Equal(TaskStatus.RanToCompletion, second.Status); Assert.False(third.IsCompleted); }
public async Task DiscoverRepositoryAsync(string filePath, CancellationToken cancellationToken) { Requires.NotNullOrEmpty(filePath, nameof(filePath)); // Switch to background thread on purpose to avoid blocking the main thread. await TaskScheduler.Default; using (await _semaphore.EnterAsync(cancellationToken)) { await DiscoverRepositoryInternalAsync(filePath, cancellationToken); } }
public async Task <MessageDialogResult> ShowMessageAsync(string title, string message) { using (await _lock.EnterAsync()) { if (ShellView != null) { return(await RunOnUIAsync(() => ShellView.ShowMessageAsync(title, message))); } return(MessageBox.Show(message, title) == MessageBoxResult.OK ? MessageDialogResult.Affirmative : MessageDialogResult.Negative); } }
// 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); } } }
protected async Task ExecuteWithLockAsync(Func <Task> func) { using (await _projectChangedSemaphore.EnterAsync().ConfigureAwait(false)) { await func().ConfigureAwait(false); } }
public async Task <T> WithLimitedCalls <T>(Func <Task <T> > onClient) { using (await _asyncSemaphore.EnterAsync(CancellationToken.None).ConfigureAwait(true)) { var timeSpan = GetDelay(); if ((DateTime.UtcNow - _lastCall).TotalSeconds < 2) { Console.WriteLine($"Limited Caller ID: {Guid} With Delay: {timeSpan.TotalSeconds}"); await Task.Delay(timeSpan).ConfigureAwait(true); } else { Console.WriteLine($"Limited Caller ID: {Guid} Without delay"); } var res = await onClient().ConfigureAwait(true); lock (_lock) { _lastCall = DateTime.UtcNow; } return(res); } }
public async Task <IConnection> GetConnectionAsync() { var connection = _sharedConnection; if (connection == null || !connection.Open) { using (await _mutex.EnterAsync()) { connection = _sharedConnection; if (connection == null || connection.Open) { _sharedConnection = null; try { connection?.Dispose(); } catch (Exception ex) { _logger.LogError(ex, "Disposing rethinkdb connection failed"); } _sharedConnection = connection = await CreateConnectionAsync(); } } } return(connection); }
public async Task <ProjectSnapshotManagerProxyState> GetProjectManagerStateAsync(CancellationToken cancellationToken) { using (await _latestStateSemaphore.EnterAsync().ConfigureAwait(false)) { if (_latestState != null) { return(_latestState); } } var projects = await GetLatestProjectsAsync(); var state = await CalculateUpdatedStateAsync(projects); return(state); }
public void InitialCapacityZero() { var sem = new AsyncSemaphore(0); Assert.Equal(0, sem.CurrentCount); Assert.False(sem.EnterAsync().IsCompleted); Assert.Equal(0, sem.CurrentCount); }
/// <inheritdoc /> public async Task <MessageDialogResult> ShowMessageAsync(string title, string message) { using (await _lock.EnterAsync()) { if (ShellView != null) { var dialogSettings = new MetroDialogSettings { AffirmativeButtonText = Resources.ChocolateyDialog_OK }; return(await ShellView.Dispatcher.Invoke(async() => { return await ShellView.ShowMessageAsync(title, message, MessageDialogStyle.Affirmative, dialogSettings); })); } return(MessageBox.Show(message, title) == MessageBoxResult.OK ? MessageDialogResult.Affirmative : MessageDialogResult.Negative); } }
private async Task <models.File> UploadThreaded(RemoteFile file, Uri parent) { using (await threadedUploadQueue.EnterAsync()) using (var platformFile = new LazyPlatformFileStream(file)) { var uploader = api.GetAsyncFileUploader( BuildUploadSpecificationRequest(file, parent, models.UploadMethod.Threaded), platformFile, threadedUploaderConfig); return(UploadResultToModel((await uploader.UploadAsync()).First())); } }
protected async Task ExecuteWithLock(Func <Task> func) { using (JoinableCollection.Join()) { using (await _lock.EnterAsync().ConfigureAwait(false)) { var task = JoinableFactory.RunAsync(func); await task.Task.ConfigureAwait(false); } } }
public async Task TooManyReleases_CopyOfStruct() { var sem = new AsyncSemaphore(2); var releaser1 = await sem.EnterAsync(); var releaser2 = await sem.EnterAsync(); // Assigning the releaser struct to another local variable copies it. var releaser2Copy = releaser2; // Dispose of each copy of the releaser. // The double-release is undetectable. The semaphore should be back at capacity 2. releaser2.Dispose(); Assert.Equal(1, sem.CurrentCount); releaser2Copy.Dispose(); Assert.Equal(2, sem.CurrentCount); releaser1.Dispose(); Assert.Equal(3, sem.CurrentCount); }
private async Task ProjectChangedBackgroundAsync(object state) { _batchingProjectChanges = false; // Ensure ordering, typically we'll only have 1 background thread in flight at a time. However, // between this line and the one prior another background thread could have also entered this // method. This is here to protect against us changing the order of project changed events. using (await _onProjectChangedInnerSemaphore.EnterAsync().ConfigureAwait(false)) { await OnProjectChangedAsync(); } }
private async Task ExecuteInitScriptsAsync() { // Fix for Bug 1426 Disallow ExecuteInitScripts from being executed concurrently by multiple threads. using (await _initScriptsLock.EnterAsync()) { if (!await _solutionManager.Value.IsSolutionOpenAsync()) { return; } Debug.Assert(_settings != null); if (_settings == null) { return; } var latestRestore = _latestRestore; var latestSolutionDirectory = await _solutionManager.Value.GetSolutionDirectoryAsync(); if (ShouldNoOpDueToRestore(latestRestore) && ShouldNoOpDueToSolutionDirectory(latestSolutionDirectory)) { _currentRestore = latestRestore; _currentSolutionDirectory = latestSolutionDirectory; return; } // We may be enumerating packages from disk here. Always do it from a background thread. await TaskScheduler.Default; var packageManager = new NuGetPackageManager( _sourceRepositoryProvider, _settings.Value, _solutionManager.Value, _deleteOnRestartManager.Value, _restoreProgressReporter.Value); var enumerator = new InstalledPackageEnumerator(_solutionManager.Value, _settings.Value); var installedPackages = await enumerator.EnumeratePackagesAsync(packageManager, CancellationToken.None); foreach (var installedPackage in installedPackages) { await ExecuteInitPs1Async(installedPackage.InstallPath, installedPackage.Identity); } // We are done executing scripts, so record the restore and solution directory that we executed for. // This aids the no-op logic above. _currentRestore = latestRestore; _currentSolutionDirectory = latestSolutionDirectory; } }
private async Task WriteToOutputChannelAsync(string channelId, string displayNameResourceId, string content, CancellationToken cancellationToken) { using (await _pipeLock.EnterAsync()) { if (_channelPipeWriter == null) { var pipe = new Pipe(); using (var outputChannelStore = await(await _serviceBrokerClient.GetValueAsync()).GetProxyAsync <IOutputChannelStore>(VisualStudioServices.VS2019_4.OutputChannelStore, cancellationToken)) { if (outputChannelStore.Proxy != null) { await outputChannelStore.Proxy.CreateChannelAsync(channelId, displayNameResourceId, pipe.Reader, TextEncoding, cancellationToken); _channelPipeWriter = pipe.Writer; // write any deferred messages foreach (var defferedMessage in _deferredOutputMessages) { // Flush when the original content is logged below await _channelPipeWriter.WriteAsync(GetBytes(defferedMessage), cancellationToken); } _deferredOutputMessages.Clear(); } else { // OutputChannel is not available so cache the output messages for later _deferredOutputMessages.Add(content); return; } } } await _channelPipeWriter.WriteAsync(GetBytes(content), cancellationToken); await _channelPipeWriter.FlushAsync(cancellationToken); } }
public async Task NoLeakForAllCanceledRequests() { var sem = new AsyncSemaphore(0); await this.CheckGCPressureAsync( async delegate { var cts = new CancellationTokenSource(); var enterTask = sem.EnterAsync(cts.Token); cts.Cancel(); await enterTask.NoThrowAwaitable(); }, maxBytesAllocated : -1, iterations : 5); }
public async Task SearchForNewObjectsAsync() { // Do not allow more than one thread to do this concurrently using (await _querySemaphore.EnterAsync()) { _lastQueryCheck = DateTime.UtcNow; // Find maximum NeDesigns ID var obj = await _rctObjectRepo.GetLegacyObjectWithHighestNeIdAsync(); if (obj != null) { var neId = obj.NeDesignId; var fails = 0; while (fails < 3) { neId++; try { _logger.LogInformation($"Querying NEDesigns for object id: {neId}"); var queryUrl = $"https://www.nedesigns.com/rct2-object/{neId}/x/"; var queryHtml = await _httpClient.GetStringAsync(queryUrl); var match = Regex.Match(queryHtml, $"/rct2-object/{neId}/(.+)/download/"); if (match.Success) { var name = match.Groups[1].Value.ToUpperInvariant(); await _rctObjectRepo.UpdateLegacyAsync( new LegacyRctObject() { NeDesignId = neId, Name = name }); _logger.LogInformation($"Adding new object: #{neId} [{name}]"); } } catch (Exception ex) { _logger.LogWarning(ex, $"Failed to query object {neId}"); fails++; } } } } }
public async Task NoLeakForContestedRequests_ThatAreCanceled(int contestingNumbers) { var sem = new AsyncSemaphore(0); var releasers = new Task <AsyncSemaphore.Releaser> [contestingNumbers]; await this.CheckGCPressureAsync( async delegate { var cts = new CancellationTokenSource(); for (int i = 0; i < releasers.Length; i++) { releasers[i] = sem.EnterAsync(cts.Token); } cts.Cancel(); await Task.WhenAll(releasers).NoThrowAwaitable(); }, maxBytesAllocated : -1, iterations : 5); }
public async Task NoLeakForUncontestedRequests(int initialCapacity) { var sem = new AsyncSemaphore(initialCapacity); var releasers = new AsyncSemaphore.Releaser[initialCapacity]; await this.CheckGCPressureAsync( async delegate { for (int i = 0; i < releasers.Length; i++) { releasers[i] = await sem.EnterAsync(); } for (int i = 0; i < releasers.Length; i++) { releasers[i].Dispose(); } }, maxBytesAllocated : -1, iterations : 5); }
public async Task AddSecretAsync(string name, string value, CancellationToken cancellationToken = default) { EnsureKeyNameIsValid(name); await TaskScheduler.Default; using (await _semaphore.EnterAsync(cancellationToken)) using (var store = await GetOrCreateStoreAsync(cancellationToken)) { if (store.ContainsKey(name)) { throw new ArgumentException(Resources.Error_SecretAlreadyExists, nameof(name)); } store.Set(name, value); await store.SaveAsync(cancellationToken); } }
private async Task ExecuteInitScriptsAsync() { // Fix for Bug 1426 Disallow ExecuteInitScripts from being executed concurrently by multiple threads. using (await _initScriptsLock.EnterAsync()) { if (!_solutionManager.IsSolutionOpen) { return; } Debug.Assert(_settings != null); if (_settings == null) { return; } var latestRestore = _latestRestore; var latestSolutionDirectory = _solutionManager.SolutionDirectory; if (ShouldNoOpDueToRestore(latestRestore) && ShouldNoOpDueToSolutionDirectory(latestSolutionDirectory)) { _currentRestore = latestRestore; _currentSolutionDirectory = latestSolutionDirectory; return; } // invoke init.ps1 files in the order of package dependency. // if A -> B, we invoke B's init.ps1 before A's. var projects = _solutionManager.GetNuGetProjects().ToList(); var packageManager = new NuGetPackageManager( _sourceRepositoryProvider, _settings, _solutionManager, _deleteOnRestartManager); var packagesByFramework = new Dictionary <NuGetFramework, HashSet <PackageIdentity> >(); var sortedGlobalPackages = new List <PackageIdentity>(); // Sort projects by type foreach (var project in projects) { // Skip project K projects. if (project is ProjectKNuGetProjectBase) { continue; } var buildIntegratedProject = project as BuildIntegratedNuGetProject; if (buildIntegratedProject != null) { var packages = await BuildIntegratedProjectUtility .GetOrderedProjectPackageDependencies(buildIntegratedProject); sortedGlobalPackages.AddRange(packages); } else { // Read packages.config var installedRefs = await project.GetInstalledPackagesAsync(CancellationToken.None); if (installedRefs?.Any() == true) { // Index packages.config references by target framework since this affects dependencies NuGetFramework targetFramework; if (!project.TryGetMetadata(NuGetProjectMetadataKeys.TargetFramework, out targetFramework)) { targetFramework = NuGetFramework.AnyFramework; } HashSet <PackageIdentity> fwPackages; if (!packagesByFramework.TryGetValue(targetFramework, out fwPackages)) { fwPackages = new HashSet <PackageIdentity>(); packagesByFramework.Add(targetFramework, fwPackages); } fwPackages.UnionWith(installedRefs.Select(reference => reference.PackageIdentity)); } } } // Each id/version should only be executed once var finishedPackages = new HashSet <PackageIdentity>(); // Packages.config projects if (packagesByFramework.Count > 0) { await ExecuteInitPs1ForPackagesConfig( packageManager, packagesByFramework, finishedPackages); } // build integrated projects if (sortedGlobalPackages.Count > 0) { await ExecuteInitPs1ForBuildIntegratedAsync( sortedGlobalPackages, finishedPackages); } // We are done executing scripts, so record the restore and solution directory that we executed for. // This aids the no-op logic above. _currentRestore = latestRestore; _currentSolutionDirectory = latestSolutionDirectory; } }
// 获得册记录信息和书目摘要信息 // 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() }); } }
// 获得册记录信息和书目摘要信息 // 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() }); } }