В моем проекте у меня есть большая часть кода, который должен выполняться в отдельном потоке без блокировки пользовательского интерфейса. Когда отладчик попадает в точку останова внутри этого кода, VS2015 зависает в течение 5-10 секунд. После этого, если я попытаюсь продолжить отладку (нажав кнопку "Шаг за шагом", "Вперед" или "Продолжить" ), приложение переходит из приостановленного состояния в рабочее состояние, инструменты отладки галочки, но ничего не происходит и 0% загрузки ЦП. Если я нажимаю Break All, тогда "cursor" (не знаю правильного термина) отображается в Application.Run( new Form1() );
в Program.cs, где Main()
есть.
Поскольку я довольно новичок в С#, я подумал, что существует некоторая проблема с моим подходом к многопоточности, но, судя по всему, все происходит независимо от того, что я пытаюсь использовать с помощью 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();
}
}