/// <summary>Releases the unmanaged resources used by the <see cref="T:System.IO.Stream" /> and optionally releases the managed resources.</summary> /// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param> protected override void Dispose(bool disposing) { if (disposing) { if (Interlocked.Exchange(ref _isDisposed, 1) == 0) { _currentStream.Dispose(); if (_tempFile != null) { var tmpName = _tempFile.Name; _tempFile = null; var tcs = new TaskCompletionSource <Nothing>(); CoreTaskHelper.RunAsyncFuncOnNewThread(async() => { try { await CloseFile(tmpName); tcs.SetResult(Nothing.Value); } catch (Exception ex) { tcs.SetException(ex); } return(Nothing.Value); }); if (!tcs.Task.Wait(TimeSpan.FromSeconds(5))) { throw new TimeoutException(); } } } } base.Dispose(disposing); }
/// <summary> /// Параллельная обработка перечисления на разных сессиях. /// </summary> /// <typeparam name="TSrc">Тип данных.</typeparam> /// <typeparam name="T">Тип результата.</typeparam> /// <param name="src">Перечисление.</param> /// <param name="parallelFunc">Функция обоработки.</param> /// <returns>Результат.</returns> protected async ValueTask <T[]> ParallelizeOnSessions <TSrc, T>(IEnumerable <TSrc> src, Func <IEsentSession, TSrc, T> parallelFunc) { ValueTask <T> Do(IEsentSession session, TSrc el) { return(session.Run(() => parallelFunc(session, el))); } if (src == null) { throw new ArgumentNullException(nameof(src)); } if (parallelFunc == null) { throw new ArgumentNullException(nameof(parallelFunc)); } var tasks = new List <ValueTask <T> >(); var toDispose = new CompositeDisposable(null); try { foreach (var el in src) { var session = await EsentProvider.GetSecondarySessionAndUse(); toDispose.AddDisposable(session.usage); tasks.Add(Do(session.session, el)); } return(await CoreTaskHelper.WhenAllValueTasks(tasks)); } finally { toDispose.Dispose(); } }
/// <summary>When overridden in a derived class, writes a sequence of bytes to the current stream and advances the current position within this stream by the number of bytes written.</summary> /// <param name="buffer">An array of bytes. This method copies <paramref name="count" /> bytes from <paramref name="buffer" /> to the current stream. </param> /// <param name="offset">The zero-based byte offset in <paramref name="buffer" /> at which to begin copying bytes to the current stream. </param> /// <param name="count">The number of bytes to be written to the current stream. </param> /// <exception cref="T:System.ArgumentException">The sum of <paramref name="offset" /> and <paramref name="count" /> is greater than the buffer length.</exception> /// <exception cref="T:System.ArgumentNullException"> /// <paramref name="buffer" /> is null.</exception> /// <exception cref="T:System.ArgumentOutOfRangeException"> /// <paramref name="offset" /> or <paramref name="count" /> is negative.</exception> /// <exception cref="T:System.IO.IOException">An I/O error occured, such as the specified file cannot be found.</exception> /// <exception cref="T:System.NotSupportedException">The stream does not support writing.</exception> /// <exception cref="T:System.ObjectDisposedException"> /// <see cref="M:System.IO.Stream.Write(System.Byte[],System.Int32,System.Int32)" /> was called after the stream was closed.</exception> /// <filterpriority>1</filterpriority> public override void Write(byte[] buffer, int offset, int count) { _currentStream.Write(buffer, offset, count); if (!CoreTaskHelper.RunAsyncFuncOnNewThread(CheckStreamSize).Wait(TimeSpan.FromSeconds(10))) { throw new TimeoutException(); } }
/// <summary>When overridden in a derived class, sets the length of the current stream.</summary> /// <param name="value">The desired length of the current stream in bytes. </param> /// <exception cref="T:System.IO.IOException">An I/O error occurs. </exception> /// <exception cref="T:System.NotSupportedException">The stream does not support both writing and seeking, such as if the stream is constructed from a pipe or console output. </exception> /// <exception cref="T:System.ObjectDisposedException">Methods were called after the stream was closed. </exception> /// <filterpriority>2</filterpriority> public override void SetLength(long value) { _currentStream.SetLength(value); if (!CoreTaskHelper.RunAsyncFuncOnNewThread(CheckStreamSize).Wait(TimeSpan.FromSeconds(10))) { throw new TimeoutException(); } }
public async Task BlobStoreUploadBenchmarkParallel() { long size; Stopwatch sw; List <BlobId> id; using (var str = new MemoryStream()) { var wr = new BinaryWriter(str); for (int i = 0; i < 1024 * 1024 * 2; i++) { wr.Write(i); } wr.Flush(); byte[] dataBuf = str.ToArray(); size = str.Length; str.Position = 0; id = new List <BlobId>(); sw = new Stopwatch(); sw.Start(); var l = new object(); async Task <Nothing> DoSave() { using (var str2 = new MemoryStream(dataBuf)) { var id1 = await _store.SaveBlob(new InputBlob() { BlobStream = str2, Category = "test", UniqueName = Guid.NewGuid().ToString() }, CancellationToken.None); lock (l) { id.Add(id1); } } return(Nothing.Value); } var toWait = Enumerable.Range(0, 5).Select(i => (Task)CoreTaskHelper.RunAsyncFuncOnNewThread(DoSave)).ToArray(); await Task.WhenAll(toWait); sw.Stop(); var sizeMb = (float)size / (1024 * 1024); var sec = sw.Elapsed.TotalSeconds / id.Count; sw = new Stopwatch(); sw.Start(); Logger.LogMessage($"Время сохранения файла размером {id.Count}x{sizeMb:F2} Мб: {sec} сек, {sizeMb / sec} Мб/Сек"); } }
private async Task <IList <IBoardPostEntity> > LoadEntities(IList <PostStoreEntityId> ids, PostStoreLoadMode mode) { ValueTask <List <IBoardPostEntity> > DoLoad(IList <PostStoreEntityId> toLoad) { return(OpenSession(session => { var result = new List <IBoardPostEntity>(); var loadContext = CreateLoadContext(session, true, true); var loadContextToDispose = loadContext; using (loadContextToDispose) { foreach (var id in toLoad) { Api.MakeKey(loadContext.table.Session, loadContext.table, id.Id, MakeKeyGrbit.NewKey); if (Api.TrySeek(loadContext.table.Session, loadContext.table, SeekGrbit.SeekEQ)) { var r = LoadBoardEntity(session, ref loadContext, mode); result.Add(r); } } } return result; })); } if (ids == null) { throw new ArgumentNullException(nameof(ids)); } mode = mode ?? DefaultLoadMode; IList <IBoardPostEntity> loaded; if (ids.Count > 4) { var toLoad = ids.DistributeToProcess(3); var tasks = toLoad.Select(DoLoad).ToArray(); var taskResults = await CoreTaskHelper.WhenAllValueTasks(tasks); loaded = taskResults.SelectMany(r => r).ToList(); } else { loaded = await DoLoad(ids); } if (mode.EntityLoadMode == PostStoreEntityLoadMode.Full) { await FillChildrenInLoadResult(loaded); } return(loaded); }
/// <summary> /// Все модули инициализированы. /// </summary> protected override async ValueTask <Nothing> OnAllInitialized() { await base.OnAllInitialized(); try { ValueTask <Nothing> DoEnsureTableversion() { return(InMainSessionAsync(EnsureTableversion)); } async ValueTask <Nothing> DoUpdate() { void SignalUpdateComplete() { _upgradeTcs.SetResult(Nothing.Value); } void SignalUpdateError(Exception ex) { _upgradeTcs.SetException(ex); } try { await TableVersionStatus.Instance.InitializeTableVersionOnce(DoEnsureTableversion); await CreateOrUpgradeTables(); CoreTaskHelper.RunUnawaitedTask(SignalUpdateComplete); } catch (Exception ex) { CoreTaskHelper.RunUnawaitedTask(() => SignalUpdateError(ex)); } return(Nothing.Value); } CoreTaskHelper.RunUnawaitedTaskAsync2(DoUpdate); } catch (Exception ex) { GlobalErrorHandler?.SignalError(ex); } return(Nothing.Value); }
/// <summary> /// ќдин раз вызвать инициализацию таблицы tableversion или ждать, если инициализаци¤ уже запущена. /// </summary> /// <param name="initFunc">‘ункци¤ инициализации.</param> public async Task InitializeTableVersionOnce(Func <ValueTask <Nothing> > initFunc) { if (initFunc == null) { throw new ArgumentNullException(nameof(initFunc)); } if (Interlocked.Exchange(ref _isProcessing, 1) == 0) { try { await CoreTaskHelper.RunAsyncFuncOnNewThreadValueTask(initFunc); _tcs.SetResult(Nothing.Value); } catch (Exception ex) { _tcs.SetException(ex); } } else { await _task; } }
private async Task <Nothing> CloseFile(string tmpName) { return(await CoreTaskHelper.RunAsyncFuncOnNewThread(async() => { var tempFile2 = await ApplicationData.Current.TemporaryFolder.GetFileAsync(tmpName); if (_moveToFolder != null && !string.IsNullOrWhiteSpace(_moveToFileName)) { try { await tempFile2.MoveAsync(_moveToFolder, _moveToFileName, NameCollisionOption.ReplaceExisting); } catch { await tempFile2.DeleteAsync(); throw; } } else { await tempFile2.DeleteAsync(); } return Nothing.Value; })); }
public async Task BoardReferenceParallelQuery() { var boards = await TestResources.LoadBoardReferencesFromResource(); var parser = _provider.FindNetworkDtoParser <MobileBoardInfoCollection, IList <IBoardReference> >(); var result = parser.Parse(boards); await _store.UpdateReferences(result, true); async Task <Nothing> Query(int cid, int qid) { Logger.LogMessage($"Query {cid}:{qid} started"); var links = result.Take(40).Select(r => r.BoardLink); foreach (var l in links) { var o = await _store.LoadReference(l); Assert.IsNotNull(o, "Не получена информация о доске"); Assert.IsTrue(BoardLinkEqualityComparer.Instance.Equals(l, o.BoardLink), "Ссылка не соответствует исходной"); } Logger.LogMessage($"Query {cid}:{qid} finished"); return(Nothing.Value); } for (var i = 0; i < 5; i++) { Logger.LogMessage($"Cycle {i} started"); await _collection.Suspend(); Logger.LogMessage("DB suspended"); await _collection.Resume(); Logger.LogMessage("DB resumed"); var cid = i; var toWait = new Task[] { CoreTaskHelper.RunAsyncFuncOnNewThread(() => Query(cid, 1)), CoreTaskHelper.RunAsyncFuncOnNewThread(() => Query(cid, 2)), CoreTaskHelper.RunAsyncFuncOnNewThread(() => Query(cid, 3)), CoreTaskHelper.RunAsyncFuncOnNewThread(() => Query(cid, 4)), CoreTaskHelper.RunAsyncFuncOnNewThread(() => Query(cid, 5)), CoreTaskHelper.RunAsyncFuncOnNewThread(() => Query(cid, 6)), CoreTaskHelper.RunAsyncFuncOnNewThread(() => Query(cid, 7)), CoreTaskHelper.RunAsyncFuncOnNewThread(() => Query(cid, 8)), CoreTaskHelper.RunAsyncFuncOnNewThread(() => Query(cid, 9)), CoreTaskHelper.RunAsyncFuncOnNewThread(() => Query(cid, 10)), CoreTaskHelper.RunAsyncFuncOnNewThread(() => Query(cid, 11)), CoreTaskHelper.RunAsyncFuncOnNewThread(() => Query(cid, 12)), CoreTaskHelper.RunAsyncFuncOnNewThread(() => Query(cid, 13)), CoreTaskHelper.RunAsyncFuncOnNewThread(() => Query(cid, 14)), CoreTaskHelper.RunAsyncFuncOnNewThread(() => Query(cid, 15)), CoreTaskHelper.RunAsyncFuncOnNewThread(() => Query(cid, 16)), CoreTaskHelper.RunAsyncFuncOnNewThread(() => Query(cid, 17)), CoreTaskHelper.RunAsyncFuncOnNewThread(() => Query(cid, 18)), CoreTaskHelper.RunAsyncFuncOnNewThread(() => Query(cid, 19)), CoreTaskHelper.RunAsyncFuncOnNewThread(() => Query(cid, 20)), CoreTaskHelper.RunAsyncFuncOnNewThread(() => Query(cid, 21)), CoreTaskHelper.RunAsyncFuncOnNewThread(() => Query(cid, 22)), CoreTaskHelper.RunAsyncFuncOnNewThread(() => Query(cid, 23)), CoreTaskHelper.RunAsyncFuncOnNewThread(() => Query(cid, 24)), CoreTaskHelper.RunAsyncFuncOnNewThread(() => Query(cid, 25)), CoreTaskHelper.RunAsyncFuncOnNewThread(() => Query(cid, 26)), CoreTaskHelper.RunAsyncFuncOnNewThread(() => Query(cid, 27)), CoreTaskHelper.RunAsyncFuncOnNewThread(() => Query(cid, 28)), CoreTaskHelper.RunAsyncFuncOnNewThread(() => Query(cid, 29)), CoreTaskHelper.RunAsyncFuncOnNewThread(() => Query(cid, 30)), }; Logger.LogMessage($"Waiting for all queries (cycle {i})"); await Task.WhenAll(toWait); Logger.LogMessage($"Waited for all queries (cycle {i})"); } }
public async ValueTask <(IEsentSession session, IDisposable disposable)> GetAvailableSession(bool autoUse) { async Task <Nothing> DoDisposeExccessSessions() { async Task DoDispose(EsentSession s) { try { await s.DisposeInternal(); } catch { // Игнорируем ошибки } } List <EsentSession> toDispose = new List <EsentSession>(); lock (Waiters.UsingLock) { var allSessions = _readonlySessions.Count; var freeSessions = _readonlySessions.Where(s => s.UsingsCount == 0).ToArray(); if (allSessions > MaxReserveSessionsCount) { toDispose.AddRange(freeSessions.Skip(ReserveSessionsCount)); } foreach (var s in toDispose) { _readonlySessions.Remove(s); } } if (toDispose.Count > 0) { var t1 = Task.WhenAll(toDispose.Select(DoDispose)); var t2 = Task.Delay(TimeSpan.FromSeconds(15)); await Task.WhenAny(t1, t2); } return(Nothing.Value); } lock (Waiters.UsingLock) { var freeSessions = _readonlySessions.Where(s => s.UsingsCount == 0).ToArray(); if (freeSessions.Length > 0) { EsentSession r; IDisposable d = null; if (freeSessions.Length == 1) { r = freeSessions[0]; } else { r = freeSessions[_rnd.Next(0, freeSessions.Length)]; } if (autoUse) { r.UsingsCount++; d = r.CreateUsageDisposable(); } return(r, d); } } var newSession = await EsentSession.CreateReadOnlySession(MainSession, Waiters); IDisposable d2 = null; lock (Waiters.UsingLock) { _readonlySessions.Add(newSession); if (autoUse) { newSession.UsingsCount++; d2 = newSession.CreateUsageDisposable(); } } CoreTaskHelper.RunUnawaitedTaskAsync(DoDisposeExccessSessions); return(newSession, d2); }
private async ValueTask <Nothing> SetChildren(IBoardPostEntity entity) { if (entity == null) { return(Nothing.Value); } ValueTask <List <IBoardPostEntity> > DoLoad(IList <(PostStoreEntityId id, int counter)> toLoad) { return(OpenSession(session => { var result = new List <IBoardPostEntity>(); var loadContext = CreateLoadContext(session, true, true); var loadContextToDispose = loadContext; using (loadContextToDispose) { foreach (var id in toLoad) { Api.MakeKey(loadContext.table.Session, loadContext.table, id.id.Id, MakeKeyGrbit.NewKey); if (Api.TrySeek(loadContext.table.Session, loadContext.table, SeekGrbit.SeekEQ)) { var r = LoadBoardEntity(session, ref loadContext, FullLoadMode); if (r is IBoardPostLight l) { l.Counter = id.counter; } result.Add(r); } } } return result; })); } var collection = entity as IBoardPostCollection; var threadCollection = entity as IBoardPageThreadCollection; if ((entity.EntityType == PostStoreEntityType.Thread || entity.EntityType == PostStoreEntityType.ThreadPreview || entity.EntityType == PostStoreEntityType.Catalog || entity.EntityType == PostStoreEntityType.BoardPage) && entity is IPostModelStoreChildrenLoadStageInfo loadStage && (collection?.Posts != null || threadCollection?.Threads != null) && entity.StoreId != null) { if (loadStage.Stage == ChildrenLoadStageId.Completed) { var childrenIds = await OpenSession(session0 => EnumEntityChildren(session0, entity.StoreId.Value)); IList <IBoardPostEntity> loaded; if (childrenIds.Count > 4) { var toLoad = childrenIds.DistributeToProcess(3); var tasks = toLoad.Select(DoLoad).ToArray(); var taskResults = await CoreTaskHelper.WhenAllValueTasks(tasks); loaded = taskResults.SelectMany(r => r).ToList(); } else { loaded = await DoLoad(childrenIds); } if (collection?.Posts != null) { IEnumerable <IBoardPost> toAdd; if (entity.EntityType == PostStoreEntityType.Catalog) { int GetCatalogSequence(IBoardPost p) { if (p is IBoardPostEntityWithSequence s) { return(s.OnPageSequence); } return(int.MaxValue); } toAdd = loaded.OfType <IBoardPost>().Deduplicate(p => p.Link, BoardLinkEqualityComparer.Instance).OrderBy(GetCatalogSequence); } else { toAdd = loaded.OfType <IBoardPost>().Deduplicate(p => p.Link, BoardLinkEqualityComparer.Instance).OrderBy(p => p.Link, BoardLinkComparer.Instance); } foreach (var item in toAdd) { collection.Posts.Add(item); } } if (threadCollection?.Threads != null) { var toAdd = loaded.OfType <IThreadPreviewPostCollection>().Deduplicate(p => p.Link, BoardLinkEqualityComparer.Instance).OrderBy(p => p.OnPageSequence); foreach (var item in toAdd) { threadCollection.Threads.Add(item); } } } } return(Nothing.Value); }