在我的项目中,我有很多代码应该在一个单独的线程上执行而不会阻塞UI。当调试器命中此代码中的断点时,VS2015会冻结5-10秒。之后,如果我尝试继续调试(通过按Step Over,Step In或Continue),应用程序从暂停状态进入工作状态,调试工具正在滴答作响,但没有任何反应,并且有0%的CPU利用率。如果我按Break All,那么"光标" (不知道正确的术语)显示在Program Application.Run( new Form1() );
Main()
所在的BackgroundWorker
。
由于我对C#很陌生,我认为我的多线程方法存在一些问题,但显然它发生在我尝试的任何地方 - 使用as {/ await with Tasks,使用new Thread(myFunc).Start()
组件,或简单的for ( int i = 0; i < Int32.MaxValue; ++i )
。
只是要清楚。
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();
}
}
函数的全新解决方案中检查了它 - 同样的问题。编辑每个请求,我不断遇到问题的测试表单代码。只有三个按钮,标签和BackgroundWorker。总体方案类似于主要项目的代码。
control: {
MaterialscategoryList:{
itemtap: "refreshList"
},
refreshList:function (list, index, target, record){
console.log("record id is " +record.get('id'));
if(record.get('id') == 1 ){
Ext.getStore('materialsid').filter('categoryId', '1');
}else if(record.get('id') == 2 ){
Ext.getStore('materialsid').filter('categoryId', '2');
}else if(record.get('id') == 3 ){
Ext.getStore('materialsid').filter('categoryId', '3');
}else if(record.get('id') == 4 ){
Ext.getStore('materialsid').filter('categoryId', '4');
}else if(record.get('id') == 5 ){
Ext.getStore('materialsid').filter('categoryId', '5');
}else if(record.get('id') == 6 ){
Ext.getStore('materialsid').filter('categoryId', '6');
}
},
答案 0 :(得分:23)
在调试多线程WinForms应用程序时,我遇到了VS2015冻结(无限期)的类似问题。
我在VS2013中调试相同的代码没有问题。
当我禁用VS托管过程时,问题似乎消失了(项目 - &gt;属性 - &gt;调试 - &gt;启用Visual Studio托管过程)。
希望对他人有用。
答案 1 :(得分:1)
我选中&#34;使用托管兼容模式&#34;在options-debugging-general中,线程调试似乎有效。
答案 2 :(得分:0)
我在2个不同的线程中有断点,当我走过时,Visual Studio从一个跳到另一个。最终它在标题栏中以(无响应)冻结。
如果我将断点限制为仅一个线程,我就不会遇到问题。
答案 3 :(得分:0)
我有类似的问题。这个问题的其他答案并没有为我解决问题,但他们指出了正确的方向。显然我选择了发布配置,而不是调试。
答案 4 :(得分:0)
烦人的时候,@ Haggisatonal的答案就是我。非常感谢你!
当我禁用VS主机进程时,问题似乎消失了 (项目 - &gt;属性 - &gt;调试 - &gt;启用Visual Studio托管 处理)。
但
喜欢在另一个Ticket中,不是我的解决方案,也许它可以帮助临时的其他人“工具 - &gt;选项 - &gt;调试 - &gt;常规 - &gt;启用属性 评估和其他隐式函数调用“
答案 5 :(得分:-1)
即使在禁用托管过程后,我也遇到了visual studio 2008冻结的问题。似乎对我有用的是禁用地址级调试。
(VS2008) 工具(菜单) - &gt;选项 - &gt;调试 - &gt;一般 - &gt; (取消选中)启用地址级调试。
答案 6 :(得分:-2)
我建议您在代码中使用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
}