Visual Studio 2015 调试在多线程应用程序中不起作用
Visual Studio 2015 Debug doesn't work in multithread application
在我的项目中,我有大量代码应该在单独的线程上执行而不会阻塞 UI。当调试器遇到此代码中的断点时,VS2015 会冻结 5-10 秒。在那之后,如果我尝试继续调试(通过按 Step Over、Step In 或 Continue),应用程序会从暂停状态变为工作状态,调试工具正在滴答作响,但什么也没有发生并且 CPU 利用率为 0% .如果我然后按 Break All,"cursor"(不知道正确的术语)显示在 Program.cs 中的 Application.Run( new Form1() );
,其中 Main()
是。
由于我是 C# 的新手,我认为我的多线程方法存在一些问题,但显然无论我尝试什么都会发生 - 使用 async/await 和任务,使用 BackgroundWorker
组件,或简单的 new Thread(myFunc).Start()
.
澄清一下。
- 代码本身运行良好。
- 调试器本身也可以工作,在我的主线程中的断点上没有冻结和 "deadlocks"。如果我从主线程启动代码 - 一切都很好。
- 我还在一个全新的解决方案中检查了一个简单的
for ( int i = 0; i < Int32.MaxValue; ++i )
函数 - 同样的问题。
- 还检查了不同版本的 .NET:4.6、4.5、4.0。到处都一样。
- 问题既没有出现在 VS2010(我以前用过),也没有出现在 VS2013(我试过只是为了确定它是 VS2015 的问题)。 不过,我朋友用同样的VS2015也没有这个问题
编辑: 每个请求,我不断遇到问题的测试表单代码。只有三个按钮,label 和 BackgroundWorker。整体方案与主工程代码类似
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
const int period = 10000;
void FuncAsync(IProgress<int> progress)
{
for ( int i = 0; i < Int32.MaxValue; ++i )
{
double part = (double)i / Int32.MaxValue;
int percent = (int)(part * 100.0);
if ( (i % period) == 0 )
progress.Report( percent );
}
}
void FuncBW(BackgroundWorker worker)
{
for ( int i = 0; i < Int32.MaxValue; ++i )
{
double part = (double)i / Int32.MaxValue;
int percent = (int)(part * 100.0);
if ( (i % period) == 0 )
worker.ReportProgress( percent );
}
}
void FuncThread()
{
for ( int i = 0; i < Int32.MaxValue; ++i )
{
double part = (double)i / Int32.MaxValue;
int percent = (int)(part * 100.0);
if ( (i % period) == 0 )
label1.Text = percent.ToString();
//yes, this one will cause exception of accessing UI from different thread
//if i press "Break" in the exception window, i will also get a 10sec freeze
}
}
private async void button1_Click(object sender, EventArgs e)
{
var progress = new Progress<int>(i => label1.Text = i.ToString() );
await Task.Factory.StartNew( () => FuncAsync( progress ),
TaskCreationOptions.LongRunning );
}
private void button2_Click(object sender, EventArgs e)
{
backgroundWorker1.RunWorkerAsync();
}
private void button3_Click(object sender, EventArgs e)
{
Thread t = new Thread(FuncThread);
t.Start();
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
FuncBW( (BackgroundWorker)sender );
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
label1.Text = e.ProgressPercentage.ToString();
}
}
我建议您在代码中使用 Timer 和 WaitHandle 的组合,而不是导致高 CPU 使用率的 for 循环。我对您的代码做了一个简单的更改,以简化 CPU 的使用。希望有所帮助。
public partial class Form1 : Form
{
EventWaitHandle _waitHandle ;
System.Timers.Timer _timer;
public Form1()
{
InitializeComponent();
_waitHandle = new EventWaitHandle(false, EventResetMode.AutoReset);
_timer = new System.Timers.Timer();
_timer.Interval = 100;
_timer.Elapsed += OnTimerElapsed;
_timer.AutoReset = true;
}
private void OnTimerElapsed(object sender, System.Timers.ElapsedEventArgs e)
{
_waitHandle.Set();
}
void FuncAsync(IProgress<int> progress)
{
_timer.Start();
int percent = 0;
while (percent <= 100)
{
if (_waitHandle.WaitOne())
{
progress.Report(percent);
percent++;
}
}
_timer.Stop();
}
void FuncBW(BackgroundWorker worker)
{
_timer.Start();
int percent = 0;
while (percent <= 100)
{
if (_waitHandle.WaitOne())
{
worker.ReportProgress(percent);
percent++;
}
}
_timer.Stop();
}
void FuncThread()
{
_timer.Start();
int percent = 0;
while (percent <= 100)
{
if (_waitHandle.WaitOne())
{
if (this.InvokeRequired)
{
this.Invoke((Action)delegate { label1.Text = percent.ToString(); });
}
else
{
label1.Text = percent.ToString();
}
percent++;
}
}
_timer.Stop();
}
... your other code
}
我在调试多线程 WinForms 应用程序时遇到过类似的 VS2015 冻结(无限期)问题。
我在 VS2013 中调试相同的代码没有问题。
当我禁用 VS 托管进程(项目 -> 属性 -> 调试 -> 启用 Visual Studio 托管进程)时,问题似乎消失了。
希望对其他人有用。
在 options-debugging-general 中检查 "use managed compatibility mode" 后,线程调试似乎可以工作。
我在 2 个不同的线程中设置了断点,Visual Studio 在我逐步执行时从一个线程跳到另一个线程。最终它在标题栏中冻结为 (Not Responding)。
如果我将断点限制在一个线程,我就不会遇到这个问题。
我遇到了类似的问题。这个问题的其他答案并没有为我解决问题,但它们为我指明了正确的方向。显然我选择了 Release 配置,而不是 Debug.
即使在禁用托管进程后,我也遇到了 visual studio 2008 冻结的问题。似乎对我有用的是禁用地址级调试。
(VS2008)
工具(菜单)-> 选项-> 调试-> 常规->(取消选中)启用地址级调试。
经过烦人的几个小时,@Haggisatonal 的回答对我来说就是这样。非常感谢!
The problem appears to go away when I disable the VS hosting process
(Project -> Properties -> Debug -> Enable the Visual Studio hosting
process).
但是
"Tools -> Options -> Debugging -> General -> Enable property
evaluation and other implicit function calls"
就像另一个票证一样,不是我的解决方案,也许它能暂时帮助其他人
在我的项目中,我有大量代码应该在单独的线程上执行而不会阻塞 UI。当调试器遇到此代码中的断点时,VS2015 会冻结 5-10 秒。在那之后,如果我尝试继续调试(通过按 Step Over、Step In 或 Continue),应用程序会从暂停状态变为工作状态,调试工具正在滴答作响,但什么也没有发生并且 CPU 利用率为 0% .如果我然后按 Break All,"cursor"(不知道正确的术语)显示在 Program.cs 中的 Application.Run( new Form1() );
,其中 Main()
是。
由于我是 C# 的新手,我认为我的多线程方法存在一些问题,但显然无论我尝试什么都会发生 - 使用 async/await 和任务,使用 BackgroundWorker
组件,或简单的 new Thread(myFunc).Start()
.
澄清一下。
- 代码本身运行良好。
- 调试器本身也可以工作,在我的主线程中的断点上没有冻结和 "deadlocks"。如果我从主线程启动代码 - 一切都很好。
- 我还在一个全新的解决方案中检查了一个简单的
for ( int i = 0; i < Int32.MaxValue; ++i )
函数 - 同样的问题。 - 还检查了不同版本的 .NET:4.6、4.5、4.0。到处都一样。
- 问题既没有出现在 VS2010(我以前用过),也没有出现在 VS2013(我试过只是为了确定它是 VS2015 的问题)。 不过,我朋友用同样的VS2015也没有这个问题
编辑: 每个请求,我不断遇到问题的测试表单代码。只有三个按钮,label 和 BackgroundWorker。整体方案与主工程代码类似
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
const int period = 10000;
void FuncAsync(IProgress<int> progress)
{
for ( int i = 0; i < Int32.MaxValue; ++i )
{
double part = (double)i / Int32.MaxValue;
int percent = (int)(part * 100.0);
if ( (i % period) == 0 )
progress.Report( percent );
}
}
void FuncBW(BackgroundWorker worker)
{
for ( int i = 0; i < Int32.MaxValue; ++i )
{
double part = (double)i / Int32.MaxValue;
int percent = (int)(part * 100.0);
if ( (i % period) == 0 )
worker.ReportProgress( percent );
}
}
void FuncThread()
{
for ( int i = 0; i < Int32.MaxValue; ++i )
{
double part = (double)i / Int32.MaxValue;
int percent = (int)(part * 100.0);
if ( (i % period) == 0 )
label1.Text = percent.ToString();
//yes, this one will cause exception of accessing UI from different thread
//if i press "Break" in the exception window, i will also get a 10sec freeze
}
}
private async void button1_Click(object sender, EventArgs e)
{
var progress = new Progress<int>(i => label1.Text = i.ToString() );
await Task.Factory.StartNew( () => FuncAsync( progress ),
TaskCreationOptions.LongRunning );
}
private void button2_Click(object sender, EventArgs e)
{
backgroundWorker1.RunWorkerAsync();
}
private void button3_Click(object sender, EventArgs e)
{
Thread t = new Thread(FuncThread);
t.Start();
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
FuncBW( (BackgroundWorker)sender );
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
label1.Text = e.ProgressPercentage.ToString();
}
}
我建议您在代码中使用 Timer 和 WaitHandle 的组合,而不是导致高 CPU 使用率的 for 循环。我对您的代码做了一个简单的更改,以简化 CPU 的使用。希望有所帮助。
public partial class Form1 : Form
{
EventWaitHandle _waitHandle ;
System.Timers.Timer _timer;
public Form1()
{
InitializeComponent();
_waitHandle = new EventWaitHandle(false, EventResetMode.AutoReset);
_timer = new System.Timers.Timer();
_timer.Interval = 100;
_timer.Elapsed += OnTimerElapsed;
_timer.AutoReset = true;
}
private void OnTimerElapsed(object sender, System.Timers.ElapsedEventArgs e)
{
_waitHandle.Set();
}
void FuncAsync(IProgress<int> progress)
{
_timer.Start();
int percent = 0;
while (percent <= 100)
{
if (_waitHandle.WaitOne())
{
progress.Report(percent);
percent++;
}
}
_timer.Stop();
}
void FuncBW(BackgroundWorker worker)
{
_timer.Start();
int percent = 0;
while (percent <= 100)
{
if (_waitHandle.WaitOne())
{
worker.ReportProgress(percent);
percent++;
}
}
_timer.Stop();
}
void FuncThread()
{
_timer.Start();
int percent = 0;
while (percent <= 100)
{
if (_waitHandle.WaitOne())
{
if (this.InvokeRequired)
{
this.Invoke((Action)delegate { label1.Text = percent.ToString(); });
}
else
{
label1.Text = percent.ToString();
}
percent++;
}
}
_timer.Stop();
}
... your other code
}
我在调试多线程 WinForms 应用程序时遇到过类似的 VS2015 冻结(无限期)问题。
我在 VS2013 中调试相同的代码没有问题。
当我禁用 VS 托管进程(项目 -> 属性 -> 调试 -> 启用 Visual Studio 托管进程)时,问题似乎消失了。
希望对其他人有用。
在 options-debugging-general 中检查 "use managed compatibility mode" 后,线程调试似乎可以工作。
我在 2 个不同的线程中设置了断点,Visual Studio 在我逐步执行时从一个线程跳到另一个线程。最终它在标题栏中冻结为 (Not Responding)。
如果我将断点限制在一个线程,我就不会遇到这个问题。
我遇到了类似的问题。这个问题的其他答案并没有为我解决问题,但它们为我指明了正确的方向。显然我选择了 Release 配置,而不是 Debug.
即使在禁用托管进程后,我也遇到了 visual studio 2008 冻结的问题。似乎对我有用的是禁用地址级调试。
(VS2008) 工具(菜单)-> 选项-> 调试-> 常规->(取消选中)启用地址级调试。
经过烦人的几个小时,@Haggisatonal 的回答对我来说就是这样。非常感谢!
The problem appears to go away when I disable the VS hosting process (Project -> Properties -> Debug -> Enable the Visual Studio hosting process).
但是
"Tools -> Options -> Debugging -> General -> Enable property evaluation and other implicit function calls"
就像另一个票证一样,不是我的解决方案,也许它能暂时帮助其他人