Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Visual Studio 2015调试不';t在多线程应用程序中工作_C#_Multithreading_Debugging_Visual Studio 2015_Visual Studio Debugging - Fatal编程技术网

C# Visual Studio 2015调试不';t在多线程应用程序中工作

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#相当陌生,我认为我的多线程处理方法存在

在我的项目中,我有大量的代码应该在单独的线程上执行,而不会阻塞UI。当调试器命中此代码中的断点时,VS2015将冻结5-10秒。之后,如果我尝试继续调试(通过按Step Over、Step In或continue),应用程序将从暂停状态变为工作状态,调试工具正在运行,但什么都没有发生,CPU利用率为0%。如果我按Break All,则“游标”(不知道正确的术语)将显示在
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在我一步通过时从一个线程跳到另一个线程。最终它在标题栏中冻结(没有响应)


    如果我将断点限制在一个线程上,我就不会遇到问题。

    我也有类似的问题。这个问题的其他答案没有为我解决问题,但它们为我指明了正确的方向。显然,我选择了发行版配置,而不是调试>