Don't capture asynclocals onto Timer

This commit is contained in:
Ben Adams 2018-09-02 13:26:52 +01:00 committed by Ryan Nowak
parent 1e8e541f65
commit 5e083c371b
2 changed files with 51 additions and 8 deletions

View File

@ -149,12 +149,35 @@ namespace Microsoft.CodeAnalysis.Razor
// Access to the timer is protected by the lock in Enqueue and in Timer_Tick
if (_timer == null)
{
// Timer will fire after a fixed delay, but only once.
_timer = new Timer(Timer_Tick, null, Delay, Timeout.InfiniteTimeSpan);
// Don't capture asynclocals onto Timer
bool restoreFlow = false;
try
{
if (!ExecutionContext.IsFlowSuppressed())
{
ExecutionContext.SuppressFlow();
restoreFlow = true;
}
// Timer will fire after a fixed delay, but only once.
_timer = new Timer(state => ((BackgroundDocumentGenerator)state).Timer_Tick(), this, Delay, Timeout.InfiniteTimeSpan);
}
finally
{
if (restoreFlow)
{
ExecutionContext.RestoreFlow();
}
}
}
}
private async void Timer_Tick(object state) // Yeah I know.
private void Timer_Tick()
{
_ = TimerTick();
}
private async Task TimerTick()
{
try
{
@ -208,7 +231,8 @@ namespace Microsoft.CodeAnalysis.Razor
{
// This is something totally unexpected, let's just send it over to the workspace.
await Task.Factory.StartNew(
() => _projectManager.ReportError(ex),
(p) => ((ProjectSnapshotManagerBase)p).ReportError(ex),
_projectManager,
CancellationToken.None,
TaskCreationOptions.None,
_foregroundDispatcher.ForegroundScheduler);
@ -218,7 +242,8 @@ namespace Microsoft.CodeAnalysis.Razor
private void ReportError(DocumentSnapshot document, Exception ex)
{
GC.KeepAlive(Task.Factory.StartNew(
() => _projectManager.ReportError(ex),
(p) => ((ProjectSnapshotManagerBase)p).ReportError(ex),
_projectManager,
CancellationToken.None,
TaskCreationOptions.None,
_foregroundDispatcher.ForegroundScheduler));

View File

@ -213,8 +213,26 @@ namespace Microsoft.VisualStudio.Editor.Razor
{
if (_idleTimer == null)
{
// Timer will fire after a fixed delay, but only once.
_idleTimer = new Timer(Timer_Tick, null, IdleDelay, Timeout.InfiniteTimeSpan);
// Don't capture asynclocals onto Timer
bool restoreFlow = false;
try
{
if (!ExecutionContext.IsFlowSuppressed())
{
ExecutionContext.SuppressFlow();
restoreFlow = true;
}
// Timer will fire after a fixed delay, but only once.
_idleTimer = new Timer(state => ((DefaultVisualStudioRazorParser)state).Timer_Tick(), this, IdleDelay, Timeout.InfiniteTimeSpan);
}
finally
{
if (restoreFlow)
{
ExecutionContext.RestoreFlow();
}
}
}
}
}
@ -337,7 +355,7 @@ namespace Microsoft.VisualStudio.Editor.Razor
}
}
private void Timer_Tick(object state)
private void Timer_Tick()
{
try
{