C# Visual Studio 2015调试不';t在多线程应用程序中工作
在我的项目中,我有大量的代码应该在单独的线程上执行,而不会阻塞UI。当调试器命中此代码中的断点时,VS2015将冻结5-10秒。之后,如果我尝试继续调试(通过按Step Over、Step In或continue),应用程序将从暂停状态变为工作状态,调试工具正在运行,但什么都没有发生,CPU利用率为0%。如果我按Break All,则“游标”(不知道正确的术语)将显示在C# Visual Studio 2015调试不';t在多线程应用程序中工作,c#,multithreading,debugging,visual-studio-2015,visual-studio-debugging,C#,Multithreading,Debugging,Visual Studio 2015,Visual Studio Debugging,在我的项目中,我有大量的代码应该在单独的线程上执行,而不会阻塞UI。当调试器命中此代码中的断点时,VS2015将冻结5-10秒。之后,如果我尝试继续调试(通过按Step Over、Step In或continue),应用程序将从暂停状态变为工作状态,调试工具正在运行,但什么都没有发生,CPU利用率为0%。如果我按Break All,则“游标”(不知道正确的术语)将显示在Application.Run(new Form1()),其中Main()为 由于我对C#相当陌生,我认为我的多线程处理方法存在
Application.Run(new Form1()),其中Main()
为
由于我对C#相当陌生,我认为我的多线程处理方法存在一些问题,但显然无论我尝试什么,都会出现问题-使用异步/等待任务、使用BackgroundWorker
组件或简单的新线程(myFunc).Start()
我只是想说清楚
- 代码本身工作得非常好
- 调试器本身也可以工作,在主线程的断点上没有冻结和“死锁”。如果我从主线程启动代码,一切都很好
- 我还在一个全新的解决方案中检查了(inti=0;I
函数的函数-同样的问题
还检查了.NET的不同版本:4.6、4.5、4.0。到处都一样
这个问题既没有出现在VS2010中(我以前使用过),也没有出现在VS2013中(我只是想确定这是一个VS2015问题)。然而,我的朋友与同样的VS2015工作也没有这个问题
编辑:每个请求,我不断发现问题的测试表单代码。只有三个按钮、标签和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();
}
}
公共部分类表单1:表单
{
公共表格1()
{
初始化组件();
}
const int period=10000;
void FuncAsync(IProgress进程)
{
对于(inti=0;ilabel1.Text=i.ToString());
等待Task.Factory.StartNew(()=>FuncAsync(进度),
TaskCreationOptions.LongRunning);
}
私有无效按钮2\u单击(对象发送者,事件参数e)
{
backgroundWorker1.RunWorkerAsync();
}
私有无效按钮3\u单击(对象发送者,事件参数e)
{
螺纹t=新螺纹(螺纹);
t、 Start();
}
私有void backgroundWorker1\u DoWork(对象发送方,DoWorkEventArgs e)
{
FuncBW((后台工作人员)发送方);
}
私有void backgroundWorker1\u ProgressChanged(对象发送方,ProgressChangedEventArgs e)
{
label1.Text=e.ProgressPercentage.ToString();
}
}
我建议您在代码中使用计时器和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
}
公共部分类表单1:表单
{
EventWaitHandle\u waitHandle;
System.Timers.Timer\u Timer;
公共表格1()
{
初始化组件();
_waitHandle=新的EventWaitHandle(false,EventResetMode.AutoReset);
_timer=新系统.Timers.timer();
_计时器。间隔=100;
_timer.appeased+=ontimerecursed;
_timer.AutoReset=true;
}
private void OnTimeRecursed(对象发送方,System.Timers.ElapsedEventArgs e)
{
_waitHandle.Set();
}
void FuncAsync(IProgress进程)
{
_timer.Start();
整数百分比=0;
虽然(百分比我在调试多线程WinForms应用程序时遇到了类似的VS2015冻结(无限期)问题
我在VS2013中调试相同的代码没有问题
当我禁用VS宿主进程(项目->属性->调试->启用VisualStudio宿主进程)时,问题似乎消失了
希望这对其他人有用。在“选项调试常规”中选中“使用托管兼容模式”后,线程调试似乎可以工作。我在两个不同的线程中有断点,Visual Studio在我一步通过时从一个线程跳到另一个线程。最终它在标题栏中冻结(没有响应)
如果我将断点限制在一个线程上,我就不会遇到问题。我也有类似的问题。这个问题的其他答案没有为我解决问题,但它们为我指明了正确的方向。显然,我选择了发行版配置,而不是调试>