提交 af1b89e8 编写于 作者: K Kevin_H

Make default implementation of GetRootAsync return the root node synchronously...

Make default implementation of GetRootAsync return the root node synchronously (rather than calling Task.Factory.StartNew).  SyntaxTree implementions that want to schedule work concurrently, etc, should override GetRootAsync.

Calling Task.Factory.StartNew with an arbitrary (current) scheduler may cause deadlocks.

Consider the case where some code calls GetRootAsync, and that method returns before the Task returned by StartNew is actually scheduled/executed.  If the caller subsequently calls Task.Wait, and the scheduler decides to "inline" the execution of the Task (execute on the same thread), then there will be a deadlock. (changeset 1407810)
上级 d43e0e62
......@@ -65,15 +65,14 @@ public abstract partial class CSharpSyntaxTree : SyntaxTree
/// <summary>
/// Gets the root node of the syntax tree asynchronously.
/// </summary>
/// <remarks>
/// By default, the work associated with this method will be executed immediately on the current thread.
/// Implementations that wish to schedule this work differently should override <see cref="GetRootAsync(CancellationToken)"/>.
/// </remarks>
public new virtual Task<CSharpSyntaxNode> GetRootAsync(CancellationToken cancellationToken = default(CancellationToken))
{
CSharpSyntaxNode node;
if (this.TryGetRoot(out node))
{
return Task.FromResult(node);
}
return Task.Factory.StartNew(() => this.GetRoot(cancellationToken), cancellationToken); // TODO: Should we use ExceptionFilter.ExecuteWithErrorReporting here?
return Task.FromResult(this.TryGetRoot(out node) ? node : this.GetRoot(cancellationToken));
}
/// <summary>
......
......@@ -82,17 +82,14 @@ public ParseOptions Options
/// <summary>
/// Gets the text of the source document asynchronously.
/// </summary>
/// <remarks>
/// By default, the work associated with this method will be executed immediately on the current thread.
/// Implementations that wish to schedule this work differently should override <see cref="GetTextAsync(CancellationToken)"/>.
/// </remarks>
public virtual Task<SourceText> GetTextAsync(CancellationToken cancellationToken = default(CancellationToken))
{
SourceText text;
if (this.TryGetText(out text))
{
return Task.FromResult(text);
}
else
{
return Task.Factory.StartNew(() => this.GetText(cancellationToken), cancellationToken);
}
return Task.FromResult(this.TryGetText(out text) ? text : this.GetText(cancellationToken));
}
/// <summary>
......
......@@ -54,13 +54,13 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
''' <summary>
''' Gets the root node of the syntax tree asynchronously.
''' </summary>
''' <remarks>
''' By default, the work associated with this method will be executed immediately on the current thread.
''' Implementations that wish to schedule this work differently should override <see cref="GetRootAsync(CancellationToken)"/>.
''' </remarks>
Public Overridable Shadows Function GetRootAsync(Optional cancellationToken As CancellationToken = Nothing) As Task(Of VisualBasicSyntaxNode)
Dim node As VisualBasicSyntaxNode = Nothing
If Me.TryGetRoot(node) Then
Return Task.FromResult(node)
End If
Return Task.Factory.StartNew(Function() Me.GetRoot(cancellationToken), cancellationToken) ' TODO: Should we use ExceptionFilter.ExecuteWithErrorReporting here?
Return Task.FromResult(If(Me.TryGetRoot(node), node, Me.GetRoot(cancellationToken)))
End Function
''' <summary>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册