Visual Studio 2015 Debug在多线程应用程序

时间:2015-08-17 13:19:10

标签: c# multithreading debugging visual-studio-2015 visual-studio-debugging

在我的项目中,我有很多代码应该在一个单独的线程上执行而不会阻塞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 )

只是要清楚。

  • 代码本身非常合适。
  • 调试器本身也可以工作,不会冻结和#34;死锁&#34;在我的主线程中的断点上。如果我从主线程启动代码 - 一切都很好。
  • 我还在一个简单的 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(); } } 函数的全新解决方案中检查了它 - 同样的问题。
  • 还检查了不同版本的.NET:4.6,4.5,4.0。同处也是。
  • 这个问题在VS2010(我之前使用过)和VS2013(我只是为了确保它是VS2015问题)中都没有出现。 然而,我的朋友使用相同的VS2015也没有这个问题。

编辑每个请求,我不断遇到问题的测试表单代码。只有三个按钮,标签和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');
     }


},

7 个答案:

答案 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托管   处理)。

  

“工具 - &gt;选项 - &gt;调试 - &gt;常规 - &gt;启用属性   评估和其他隐式函数调用“

喜欢在另一个Ticket中,不是我的解决方案,也许它可以帮助临时的其他人

答案 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
    }