Sar*_*ger 5 c# multithreading asynchronous vsix visual-studio-2019
Microsoft 将 VSIX 更改为与 VS2019 异步,随之而来的是悲伤。
我看到很多警告说:
警告 VSTHRD010 访问“项目”应该只在主线程上完成。首先调用 Microsoft.VisualStudio.ProjectSystem.IProjectThreadingService.VerifyOnUIThread()。
我确实添加了,虽然想删除 Nuget 包Microsoft.VisualStudio.ProjectSystem,但没有帮助。
将该行添加到方法的顶部会产生:
错误 CS0120 非静态字段、方法或属性“IProjectThreadingService.VerifyOnUIThread()”需要对象引用
搜索对解决最后一个错误没有帮助。
我尝试添加:
`Microsoft.VisualStudio.Shell.ThreadHelper.ThrowIfNotOnUIThread();
但这并没有改变事情。
想法?
更新
我认为接近投票是来自说提供代码的用户。没有“代码”。任何从 VS2019 之前升级到 VS2019 并遇到同步 VSIX 到异步 VSIX 的人都会理解这个问题。不能像以前那样只使用物品。由于 VS 现在将许多元素仅分类为“主 UI 可访问”,因此出现了许多此类警告。这意味着
if (null == oItems || 0 == oItems.Count)
return false;
Run Code Online (Sandbox Code Playgroud)
不再有效。oItems 定义为 EnvDTE。ProjectItems. Hence the warning访问 ProjectItems . Basically, anything inEnvDTE` 是不受限制的。
代码将是任何接触/使用 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;
}
Run Code Online (Sandbox Code Playgroud)
返回的信息性消息是:
严重性 VSTHRD102 将同步阻塞方法调用(例如 JoinableTaskFactory.Run 或 Task.Result)的使用限制为必须同步的公共入口点成员。将其用于内部成员可能会在异步帧之间不必要地添加同步帧,从而导致线程池耗尽。
当迁移到 AsyncPackage 或其他新的异步上下文时,如果您不在主线程上,切换到主线程可能比断言/抛出更容易。这通常通过 await 来完成JoinableTaskFactory.SwitchToMainThreadAsync()。
JoinableTaskFactory继承自AsyncPackage,或者也可以通过 访问Microsoft.VisualStudio.Shell.ThreadHelper。
如果你在一个不再在 UI 线程上的同步方法中并希望委托给它,一个常见的模式是:
// 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();
});
Run Code Online (Sandbox Code Playgroud)
可以在VS Threading Cookbook 中找到有关此主题的更多信息。
编辑:对回应的回应......
VSTHRD102 错误来自使用同步等待。正如我所提到的,JTF.Run()在 UI 线程上完成工作时会阻塞当前线程(task.Wait()或task.Result)。基本上你消耗了 2 个线程,而实际上只使用了一个线程,因此分析器会抱怨(这样做太频繁了,线程池将被耗尽,因为所有线程最终都处于同步阻塞状态)。
VS 中推出的线程设计更改将导致您:
async Task<T>以便您可以等待JTF.RunAsync()(或JTF.SwitchToMainThreadAsync()直接等待)。JTF.RunAsync()非异步方法将您的代码转换为通过即发即弃风格的任务运行。说到 VS 中的挂起,在示例代码的 EventOptionsDialog 方法中,您正在使用System.Threading.Tasks.Task.Run(). 这在 VS(或者可能是任何其他具有 UI 线程问题的应用程序)中也可能是危险的,因为 Task.Run 不支持重入。例如,如果 UI 线程上的某些内容等待Task.Run(您没有等待,但只是为了示例),这将阻塞 UI 线程,并且如果委托的工作尝试在 UI 线程上安排更多工作,会死锁挂VS。使用 JTF 将缓解这个问题,因为它确实在某种程度上跟踪了重入场景。
| 归档时间: |
|
| 查看次数: |
1386 次 |
| 最近记录: |