Hacktoberfest 2026:维护者为十月标记出来的 issue,仍然开放、适合新手。 浏览 Hacktoberfest issue

VS hangs: project options reactor reads the caret through UI-thread COM while the UI thread waits for the reactor

未关闭
#20,522 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

评估

难度
4/5
预计耗时
3-5 天
新手友好度
48/100
Issue 类型
缺陷
描述清晰度
基本清楚
活跃度
活跃
技术栈
fsharp
领域
devtools

调研方向

从 Common/Extensions.fs 和 LanguageService/FSharpProjectOptionsManager.fs 开始,跟踪 FSharpProjectOptionsReactor.textViewAndCaret 经过 getProjectOptionsFromScript 的流程。检查 ScriptClosure.resolveDependencyManagerSources 如何使用 caret,以及非脚本 .fs 文件如何订阅 IVsTextViewEvents。当 reactor 不再等待 UI thread 且非脚本文件不请求 caret 数据时,即表示完成。

由索引模型根据 Issue 内容生成。

描述

Needs-Triage

Visual Studio can hang for good when the project options reactor computes options for a document in F# Miscellaneous Files or for a script while the UI thread synchronously waits for those options. The reactor asks the UI thread for the caret, and the UI thread is blocked waiting for the reactor.

The caret lookup came with #18393, which gave GetProjectOptionsFromScript a caret so that a #r "nuget: …" line is not resolved while it is still being typed (#18231).

Repro steps

Caught once in the debugger, not reproduced on demand. The window is any synchronous UI-thread wait on project options for such a document while the reactor is busy with it. Here it was:

  1. A solution restored with an F# document tab whose project is not loaded, so the file opened in F# Miscellaneous Files, with breakpoints set in it.
  2. An extension's QueryStatus asked the not-yet-loaded frame for its text view, which forced EnsureDocumentFrameLoaded.
  3. Showing the frame made the debugger validate the breakpoint locations on the UI thread.

Actual behavior

Project options reactor thread:

Microsoft.VisualStudio.Services.VsTask.InternalGetResult
Microsoft.VisualStudio.Shell.ServiceProvider.QueryService
Microsoft.VisualStudio.Shell.ServiceProvider.GetService
Extensions.Document.TryGetIVsTextView              Common/Extensions.fs
Extensions.Document.TryGetTextViewAndCaretPos      Common/Extensions.fs
FSharpProjectOptionsReactor.textViewAndCaret       LanguageService/FSharpProjectOptionsManager.fs
FSharpProjectOptionsReactor.getProjectOptionsFromScript
  … tryComputeOptionsBySingleScriptOrFile, started from the reactor's MailboxProcessor loop

UI thread:

Microsoft.VisualStudio.Threading.JoinableTaskFactory.WaitSynchronouslyCore
Microsoft.VisualStudio.Threading.JoinableTask.CompleteOnCurrentThread
AbstractLanguageService<FSharpPackage, FSharpLanguageService>.VsLanguageDebugInfo.ValidateBreakpointLocation
Microsoft.VisualStudio.Platform.WindowManagement.Rdt.NotifyOnBeforeShow
WindowFrame.NotifyFrameShowing / ShowInternal / Show / TryReplacePlaceholderView
WindowFrame.LoadDocumentFrameInternalAsync
WindowFrame.EnsureDocumentFrameLoaded / GetProperty
  … an extension's IOleCommandTarget.QueryStatus asking for the active text view

ValidateBreakpointLocation goes through F# breakpoint resolution to the parse results and so to the reactor, which sits on the first stack. ServiceProvider.GlobalProvider.GetService called off the UI thread needs the UI thread, and so do the RDT, IVsTextManager.GetActiveView, IVsTextView.GetCaretPos and the IVsTextViewEvents connection point that follow it. The reactor is a MailboxProcessor, so its work is not joined to the JoinableTask the UI thread waits for, and JTF.Run never runs the request. Switching the reactor to the UI thread with SwitchToMainThreadAsync would hang the same way.

The document here was a plain .fs file, for which the caret is useless: ScriptClosure.resolveDependencyManagerSources is its only reader, and only scripts have #r "nuget: …" lines. The same path also subscribed to IVsTextViewEvents for every such .fs file and recomputed script options on every caret line change.

Expected behavior

The reactor never waits for the UI thread: the UI thread publishes the caret, the reactor reads it, and files that are not scripts do not look for it at all.

Related information

  • Windows 11, Visual Studio 18 Insiders, experimental instance
  • The code path is unchanged on main
主要语言
F#
星标
4.3k
派生
877
平均合并
6 天 11 小时
30 天内合并 PR
150

贡献指南

打开贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

dotnet/fsharp 的其他 Issue

查看 dotnet/fsharp 的全部 Issue

相似的 Issue

更多 DevTools Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。