簡體   English   中英

Visual Studio 2015 Debug在多線程應用程序中不起作用

[英]Visual Studio 2015 Debug doesn't work in multithread application

在我的項目中,我有很多代碼應該在一個單獨的線程上執行而不會阻塞UI。 當調試器命中此代碼中的斷點時,VS2015會凍結5-10秒。 之后,如果我嘗試繼續調試(通過按Step Over,Step In或Continue),應用程序將從暫停狀態進入工作狀態,調試工具正在滴答作響,但沒有任何反應,CPU利用率為0%。 如果我按Break All然后,在Application.Run( new Form1() );顯示“光標”(不知道正確的術語Application.Run( new Form1() ); 在Program.cs中Main()是。

由於我對C#很陌生,我認為我的多線程方法存在一些問題,但顯然它發生在我嘗試的任何地方 - 使用async / await與Tasks,使用BackgroundWorker組件或簡單的new Thread(myFunc).Start()

只是為了清楚。

  • 代碼本身非常好用。
  • 調試器本身也可以工作,在主線程中的斷點上沒有凍結和“死鎖”。 如果我從主線程啟動代碼 - 一切都很好。
  • 我還在一個簡單的for ( int i = 0; i < Int32.MaxValue; ++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();
    }
}

在調試多線程WinForms應用程序時,我遇到了VS2015凍結(無限期)的類似問題。

我在VS2013中調試相同的代碼沒有問題。

當我禁用VS主機進程(項目 - >屬性 - >調試 - >啟用Visual Studio主機進程)時,問題似乎消失了。

希望對別人有用。

我在options-debugging-general中檢查了“使用托管兼容模式”后,線程調試似乎有效。

我在兩個不同的線程中有斷點,當我走過時,Visual Studio從一個跳到另一個。 最終它在標題欄中以(無響應)凍結。

如果我將斷點限制為只有一個線程 ,我就不會遇到問題。

我有一個類似的問題。 這個問題的其他答案並沒有為我解決問題,但他們指出了正確的方向。 顯然我選擇了Release配置,而不是Debug

煩人的時候,@ Haggisatonal的答案就是我。 非常感謝你!

當我禁用VS主機進程(項目 - >屬性 - >調試 - >啟用Visual Studio主機進程)時,問題似乎消失了。

“工具 - >選項 - >調試 - >常規 - >啟用屬性評估和其他隱式函數調用”

就像在另一張票中一樣,對我來說不是解決方案,也許它可以幫助臨時其他人

即使在禁用托管過程后,我也遇到了visual studio 2008凍結的問題。 似乎對我有用的是禁用地址級調試。

(VS2008)工具(菜單) - >選項 - >調試 - >常規 - >(取消選中)啟用地址級調試。

我建議您在代碼中使用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
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM