gpt4 book ai didi

c# - VSTHRD010 : Accessing item should only be done on the main thread

转载 作者:太空宇宙 更新时间:2023-11-03 14:39:57 27 4
gpt4 key购买 nike

Microsoft 将 VSIX 更改为与 VS2019 异步,随之而来的是悲痛。

我看到很多警告说:

Warning VSTHRD010 Accessing "Project" should only be done on the main thread. Call Microsoft.VisualStudio.ProjectSystem.IProjectThreadingService.VerifyOnUIThread() first.

我确实添加了 Nuget 包 Microsoft.VisualStudio.ProjectSystem,尽管考虑删除,但这并没有帮助。

将该行添加到方法的顶部会产生:

Error CS0120 An object reference is required for the non-static field, method, or property 'IProjectThreadingService.VerifyOnUIThread()'

搜索对解决最后一个错误没有帮助。

我尝试添加:

`Microsoft.VisualStudio.Shell.ThreadHelper.ThrowIfNotOnUIThread();

但这并没有改变什么。

想法?

更新

我认为接近的投票来自说要提供代码的用户。没有“代码”。任何从 VS2019 之前升级到 VS2019 并遇到同步 VSIX 到异步 VSIX 的人都会理解这个问题。不能像以前那样只使用元素。由于 VS 现在将许多元素归类为“仅可访问主 UI”,因此出现了许多此类警告。这意味着

if (null == oItems || 0 == oItems.Count)
return false;

不再有效。 oItems 定义为 EnvDTE.ProjectItems。因此出现了警告Accessing ProjectItems。基本上,EnvDTE` 中的任何内容都是禁止访问的。

代码将是任何接触/使用 EnvDTE 对象的东西。

对答案 1 的回应

我实现了答案并抛出了一个新错误。

private void MenuItemCallback(object sender, EventArgs e)
{
info VSTHRD102 -> this.packageVsi.JoinableTaskFactory.Run(async () =>
{
await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
this.EventOptionsDialog();
});
}

private Task EventOptionsDialog()
{
_ = System.Threading.Tasks.Task.Run(async () =>
{
await this.packageVsi.DoTask1Async();
}
);

// Other tasks

return null;
}

返回的信息性消息是:

Severity VSTHRD102 Limit use of synchronously blocking method calls such as JoinableTaskFactory.Run or Task.Result to public entrypoint members where you must be synchronous. Using it for internal members can needlessly add synchronous frames between asynchronous frames, leading to threadpool exhaustion.

  1. 我想要干净的工作代码,所以没有消息、警告或错误。
  2. 有大量代码需要解决方案,因此如果该技术耗尽了线程池,那么这个答案就不好。
  3. 有很多下游方法,据我观察,VS2019 很愚蠢,但不知道子方法已经有主 UI。这个过程有点复杂,因为一些方法是从多个位置调用的。
  4. 我仍然想要没有添加许多新代码块的干净代码。

最佳答案

当迁移到 AsyncPackage 或其他新的异步上下文时,如果您不在主线程上,切换到主线程可能比断言/抛出更容易。这通常通过等待 JoinableTaskFactory.SwitchToMainThreadAsync() 来完成。 .

JoinableTaskFactory继承自 AsyncPackage , 或者也可以通过 Microsoft.VisualStudio.Shell.ThreadHelper 访问.

如果您在一个不再在 UI 线程上的同步方法中并希望委托(delegate)给它,一个常见的模式是:

// Fire-and-forget
JoinableTaskFactory.RunAsync(async () =>
{
await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
DoWork();
});

// Synchronously block the current thread and wait.
// Not recommended - can lead to thread pool starvation if over-used.
JoinableTaskFactory.Run(async () =>
{
await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
DoWork();
});

有关此主题的更多信息可以在 VS Threading Cookbook 中找到.

编辑:对响应的响应...

VSTHRD102 错误来自于使用同步等待。正如我提到的,JTF.Run()在 UI 线程上完成工作时阻塞当前线程(同上 task.Wait()task.Result )。基本上你消耗了 2 个线程,而实际上只使用了一个,因此分析器会提示(这样做太频繁,线程池将被耗尽,因为所有线程最终都处于同步阻塞状态)。

VS 中推出的线程设计更改将导致您:

  • 将您的方法转换为 async Task<T>这样你就可以等待JTF.RunAsync() (或直接等待 JTF.SwitchToMainThreadAsync())。
  • 使用 JTF.RunAsync() 将您的代码转换为通过即发即弃式任务运行来自非异步方法。
  • 抑制这些分析器警告。请仅将此作为经过仔细考虑的最后手段,因为它们旨在缓解导致性能问题或 VS 挂起的常见情况。

说到 VS 中的挂起,在示例代码的 EventOptionsDialog 方法中,您使用的是 System.Threading.Tasks.Task.Run() .这在 VS(或者可能是任何其他具有 UI 线程问题的应用程序)中也可能是危险的,因为 Task.Run 不支持重新进入。例如,如果 UI 线程上的某些内容等待 Task.Run(您没有等待,但为了举例),这将阻塞 UI 线程,并且如果委派的工作尝试安排更多的工作回到 UI 线程,它会死锁并挂起 VS。使用 JTF 可以缓解这个问题,因为它确实在某种程度上跟踪了重入场景。

关于c# - VSTHRD010 : Accessing item should only be done on the main thread,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57597098/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com