提交 da2aabf8 编写于 作者: J Jason Malinowski

Extract a common use of AsyncBatchingWorkQueue into AsyncBatchingDelay

We have a common pattern where we are using an AsyncBatchingWorkQueue
to have a simple batching delay so we don't process things too quickly.
Rather than having each time we do this pattern explain what the value
is (and why it doesn't matter) we can just extract it out.
上级 a52e4abc
......@@ -3,7 +3,6 @@
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Editor.Tagging;
......@@ -17,7 +16,7 @@ internal partial class TaggerEventSources
{
private class WorkspaceChangedEventSource : AbstractWorkspaceTrackingTaggerEventSource
{
private readonly AsyncBatchingWorkQueue<bool> _workQueue;
private readonly AsyncBatchingDelay _asyncDelay;
public WorkspaceChangedEventSource(
ITextBuffer subjectBuffer,
......@@ -25,17 +24,15 @@ private class WorkspaceChangedEventSource : AbstractWorkspaceTrackingTaggerEvent
IAsynchronousOperationListener asyncListener)
: base(subjectBuffer, delay)
{
// Pass in an equality comparer here. That will ensure that even if we get a flurry of workspace
// events that we only ever have one entry in the workqueue as all other events will dedupe against
// that one.
_workQueue = new AsyncBatchingWorkQueue<bool>(
// That will ensure that even if we get a flurry of workspace events that we
// only process a tag change once.
_asyncDelay = new AsyncBatchingDelay(
TimeSpan.FromMilliseconds(250),
processBatchAsync: (_1, _2) =>
processAsync: cancellationToken =>
{
RaiseChanged();
return Task.CompletedTask;
},
equalityComparer: EqualityComparer<bool>.Default,
asyncListener,
CancellationToken.None);
}
......@@ -53,7 +50,7 @@ protected override void DisconnectFromWorkspace(Workspace workspace)
}
private void OnWorkspaceChanged(object sender, WorkspaceChangeEventArgs eventArgs)
=> _workQueue.AddWork(true);
=> _asyncDelay.RequeueWork();
}
}
}
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Shared.TestHooks;
using Roslyn.Utilities;
namespace Roslyn.Utilities
{
internal sealed class AsyncBatchingDelay
{
private readonly AsyncBatchingWorkQueue<bool> _workQueue;
private readonly Func<CancellationToken, Task> _processAsync;
public AsyncBatchingDelay(
TimeSpan delay,
Func<CancellationToken, Task> processAsync,
IAsynchronousOperationListener? asyncListener,
CancellationToken cancellationToken)
{
_processAsync = processAsync;
// We use an AsyncBatchingWorkQueue with a boolean, and just always add the
// same value at all times.
_workQueue = new AsyncBatchingWorkQueue<bool>(
delay,
OnNotifyAsync,
equalityComparer: EqualityComparer<bool>.Default,
asyncListener,
cancellationToken);
}
private Task OnNotifyAsync(ImmutableArray<bool> _, CancellationToken cancellationToken)
{
return _processAsync(cancellationToken);
}
public void RequeueWork()
{
// Value doesn't matter here as long as we're consistent.
_workQueue.AddWork(item: false);
}
}
}
......@@ -147,13 +147,10 @@ internal partial class SQLitePersistentStorage : AbstractPersistentStorage
_insert_into_string_table_values_0 = $@"insert into {StringInfoTableName}(""{DataColumnName}"") values (?)";
_select_star_from_string_table_where_0_limit_one = $@"select * from {StringInfoTableName} where (""{DataColumnName}"" = ?) limit 1";
// Create a queue to batch up requests to flush. We'll won't flush more than every FlushAllDelayMS. The
// actual information in the queue isn't relevant, so we pass in an equality comparer to just keep it down
// to storing a single piece of data.
_flushQueue = new AsyncBatchingWorkQueue<bool>(
// Create a delay to batch up requests to flush. We'll won't flush more than every FlushAllDelayMS.
_flushQueue = new AsyncBatchingDelay(
TimeSpan.FromMilliseconds(FlushAllDelayMS),
FlushInMemoryDataToDiskIfNotShutdownAsync,
EqualityComparer<bool>.Default,
asyncListener: null,
_shutdownTokenSource.Token);
}
......
......@@ -16,15 +16,14 @@ internal partial class SQLitePersistentStorage
/// A queue to batch up flush requests and ensure that we don't issue then more often than every <see
/// cref="FlushAllDelayMS"/>.
/// </summary>
private readonly AsyncBatchingWorkQueue<bool> _flushQueue;
private readonly AsyncBatchingDelay _flushQueue;
private void EnqueueFlushTask()
{
// actual value isn't relevant. this just ensures that a flush will happen in the future.
_flushQueue.AddWork(true);
_flushQueue.RequeueWork();
}
private Task FlushInMemoryDataToDiskIfNotShutdownAsync(ImmutableArray<bool> _, CancellationToken cancellationToken)
private Task FlushInMemoryDataToDiskIfNotShutdownAsync(CancellationToken cancellationToken)
{
// When we are asked to flush, go actually acquire the write-scheduler and perform the actual writes from
// it. Note: this is only called max every FlushAllDelayMS. So we don't bother trying to avoid the delegate
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册