Почему окно консоли закрывается сразу после отображения моего вывода?


158

Я изучаю C #, следуя инструкциям в MSDN .

Теперь я только что попробовал Пример 1 ( здесь ссылка на MSDN ), и я столкнулся с проблемой: почему окно консоли закрывается сразу после отображения моего вывода?

using System;

public class Hello1
{
    public static int Main()
    {
        Console.WriteLine("Hello, World!");
        return 0;
    }
}

Вы можете попробовать открыть с консоли. Перетащите его на консоль и нажмите «Enter». Я предполагаю, что это файл EXE.
Саджидур Рахман

Если вы пытаетесь отладить программу командной строки, которая запускается внешним процессом, посмотрите этот вопрос: stackoverflow.com/a/23334014/3195477
UuDdLrLrSs

Ответы:


267

проблема здесь в том, что их Hello World Program показывает, то она будет немедленно закрыта.
это почему?

Потому что это закончено. Когда консольные приложения завершат выполнение и вернутся из своего mainметода, соответствующее консольное окно автоматически закроется. Это ожидаемое поведение.

Если вы хотите, чтобы он оставался открытым для целей отладки, вам нужно будет дать компьютеру команду подождать нажатия клавиши, прежде чем завершать работу приложения и закрывать окно.

Console.ReadLineМетод является одним из способов сделать это. Добавление этой строки в конец кода (непосредственно перед returnоператором) приведет к тому, что приложение будет ждать, пока вы нажмете клавишу, прежде чем выйти.

В качестве альтернативы, вы можете запустить приложение без подключенного отладчика, нажав « CtrlF5в среде Visual Studio, но это имеет очевидный недостаток, заключающийся в том, что вы не можете использовать функции отладки, которые вы, вероятно, захотите использовать при написании приложения.

Наилучшим компромиссом, вероятно, является вызов Console.ReadLineметода только при отладке приложения, заключая его в директиву препроцессора. Что-то вроде:

#if DEBUG
    Console.WriteLine("Press enter to close...");
    Console.ReadLine();
#endif

Вы также можете захотеть, чтобы окно оставалось открытым, если было выброшено необработанное исключение. Для этого вы можете поместить Console.ReadLine();в finallyблок:

#if DEBUG
    try
    {
        //...
    }
    finally
    {
        Console.WriteLine("Press enter to close...");
        Console.ReadLine();
    }
#endif

18
Кроме того, вы можете использовать Console.ReadKey ();
PlantationGator

55
Лично я предпочитаю if (System.Diagnostics.Debugger.IsAttached) Console.ReadLine();.
Самер Сингх

5
Почему работа без отладки меняет это поведение? Вы думаете, что это должен быть более точный опыт, а не меньше.
Кайл Делани

@SameerSingh Еще одна строка ненужного кода компилируется в ваш двоичный файл. Я на самом деле предпочитаю этот препроцессорный подход.
Джоэл

@ Джоэль Почему мы вообще должны заботиться об этом в эти дни?
Алекс

66

Вместо того, чтобы использовать

Console.Readline()
Console.Read()
Console.ReadKey()

Вы можете запустить вашу программу, используя Ctrl+ F5(если вы находитесь в Visual Studio). Затем Visual Studio будет держать окно консоли открытым, пока вы не нажмете клавишу.

Примечание: вы не можете отлаживать свой код в этом подходе.


Привет, пользователь. Я новый пользователь VS и C # в целом. Что делает по- Ctrl + F5другому, что просто довольно по- Startдругому?
theGreenCabbage

к сожалению, иногда он перестает работать, как ожидалось.
MaikoID

2
Причиной проблемы является то, что Windows автоматически закрывает окно терминала при остановке программы. Другие системы будут держать окно открытым автоматически. Это гораздо лучший способ запустить программу. Не используйте ReadKey, Read или ReadLine для этого материала, так как это предотвращает использование вашей программы в сочетании с другими консольными приложениями и трубопроводами.
режиме реального времени

14

Я предполагаю, что причина, по которой вы не хотите, чтобы он закрывался в режиме отладки, заключается в том, что вы хотите посмотреть значения переменных и т. Д. Поэтому, вероятно, лучше всего просто вставить точку останова в закрывающую "}" главной функции. , Если вам не нужно отлаживать, то Ctrl-F5 - лучший вариант.


Удивленный, ни один из других ответов не предложил это. Редко, когда ответ с новой опцией добавляется так поздно после создания вопроса.
Скотт Чемберлен

13

Это ведет себя так же для CtrlF5или F5. Поместите непосредственно перед концом Mainметода.

using System.Diagnostics;

private static void Main(string[] args) {

  DoWork();

  if (Debugger.IsAttached) {
    Console.WriteLine("Press any key to continue . . .");
    Console.ReadLine();
  }
}

7
Просто чтобы отметить, последняя строка должна быть Console.ReadKey()для любой клавиши, Console.ReadLine()ждет нажатия Enter
Крис

6

Программа немедленно закрывается, потому что ничто не мешает ей закрыться. Вставьте точку останова на return 0;или добавьте Console.Read();перед, return 0;чтобы предотвратить закрытие программы.


5

Я немного опоздал на вечеринку, но: в Visual Studio 2019 для проектов .NET Core консоль не закрывается автоматически по умолчанию. Вы можете настроить поведение через меню Инструменты → Параметры → Отладка → Общие → Автоматически закрыть консоль, когда отладка останавливается. Если окно консоли закрывается автоматически, проверьте, не задан ли упомянутый параметр.

То же самое относится и к консольным проектам нового стиля .NET Framework:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net472</TargetFramework>
  </PropertyGroup>

</Project>

Старый стиль .NET Framework по-прежнему безоговорочно закрывал консоль в конце (начиная с Visual Studio 16.0.1).

Ссылка: https://devblogs.microsoft.com/dotnet/net-core-tooling-update-for-visual-studio-2019-preview-2/


Эта опция доступна для меня в VS2017 15.9.4, но она не работает для моего консольного приложения .net core 2.1 ...
user1073075

@ user1073075: это странно. Работает ли эта функция для других целей?
Влад

Нет. Пробовал с консольным приложением .NET Framework и все еще не работал. (Я установил VS2019 на другой машине, и там это работает. Может быть, это ошибка в VS17 15.9.4)
user1073075

С 2019 года он теперь работает даже для проектов WPF: pastebin.com/FpAeV0cW . Но вы должны установить .NET Core 3.
Влад

5

Если вы хотите, чтобы ваше приложение было открыто, вам нужно что-то сделать, чтобы поддержать его процесс. Приведенный ниже пример является самым простым, который нужно поместить в конец вашей программы:

while (true) ;

Тем не менее, это вызовет перегрузку ЦП, поскольку он вынужден выполнять итерации бесконечно.

На этом этапе вы можете выбрать использование System.Windows.Forms.Applicationкласса (но для этого необходимо добавить System.Windows.Formsссылку):

Application.Run();

Это не пропускает процессор и работает успешно

Чтобы избежать добавления System.Windows.Formsссылки, вы можете использовать простой трюк, так называемое ожидание вращения , импортирующий System.Threading:

SpinWait.SpinUntil(() => false);

Это также отлично работает и в основном состоит из whileцикла с отрицательным условием, которое возвращается вышеприведенным лямбда-методом. Почему это не перегрузка процессора? Вы можете посмотреть исходный код здесь ; во всяком случае, он в основном ждет некоторого цикла процессора, прежде чем перебирать.

Вы также можете создать зацикливатель сообщений, который просматривает ожидающие сообщения из системы и обрабатывает каждое из них, прежде чем перейти к следующей итерации, следующим образом:

[DebuggerHidden, DebuggerStepperBoundary, DebuggerNonUserCode, DllImport("user32.dll", EntryPoint = "PeekMessage")]
public static extern int PeekMessage(out NativeMessage lpMsg, IntPtr hWnd, int wMsgFilterMin, int wMsgFilterMax, int wRemoveMsg);

[DebuggerHidden, DebuggerStepperBoundary, DebuggerNonUserCode, DllImport("user32.dll", EntryPoint = "GetMessage")]
public static extern int GetMessage(out NativeMessage lpMsg, IntPtr hWnd, int wMsgFilterMin, int wMsgFilterMax);

[DebuggerHidden, DebuggerStepperBoundary, DebuggerNonUserCode, DllImport("user32.dll", EntryPoint = "TranslateMessage")]
public static extern int TranslateMessage(ref NativeMessage lpMsg);

[DebuggerHidden, DebuggerStepperBoundary, DebuggerNonUserCode, DllImport("user32.dll", EntryPoint = "DispatchMessage")]
public static extern int DispatchMessage(ref NativeMessage lpMsg);

[DebuggerHidden, DebuggerStepperBoundary, DebuggerNonUserCode]
public static bool ProcessMessageOnce()
{
    NativeMessage message = new NativeMessage();

    if (!IsMessagePending(out message))
        return true;

    if (GetMessage(out message, IntPtr.Zero, 0, 0) == -1)
        return true;

    Message frameworkMessage = new Message()
    {
        HWnd = message.handle,
        LParam = message.lParam,
        WParam = message.wParam,
        Msg = (int)message.msg
    };

    if (Application.FilterMessage(ref frameworkMessage))
        return true;

    TranslateMessage(ref message);
    DispatchMessage(ref message);

    return false;
}

Затем вы можете безопасно выполнить цикл, выполнив что-то вроде этого:

while (true)
    ProcessMessageOnce();

Я не знаю, если это утечка процессора или нет, но; работает успешно. Спасибо.
Мумин Ка

4

Кроме того, вы можете отложить закрытие, используя следующий код:

System.Threading.Thread.Sleep(1000);

Обратите внимание, что Sleepиспользуется миллисекунды.


4

Другой способ - использовать Debugger.Break()перед возвратом из метода Main.


Хотя это переключает фокус обратно на окно отладчика и потенциально скрывает содержимое окна консоли.
Стивен Тернер

3

Код закончен, для продолжения необходимо добавить это:

Console.ReadLine();

или

Console.Read();

3

Используйте Console.Read (); чтобы предотвратить закрытие программы, но убедитесь, что вы добавили Console.Read();код перед оператором возврата, иначе это будет недоступный код.

    Console.Read(); 
    return 0; 

проверить эту консоль.Читать


3

Добавьте Readметод, чтобы показать вывод.

Console.WriteLine("Hello, World!");
Console.Read();
return 0;


0

Программа закрывается, как только ее выполнение завершено. В этом случае, когда вы return 0;. Это ожидаемая функциональность. Если вы хотите увидеть вывод, то либо запустите его вручную в терминале, либо установите ожидание в конце программы, чтобы он оставался открытым в течение нескольких секунд (используя библиотеку потоков).



-3

если ваша программа требует, чтобы вы продолжили нажимать клавишу ввода, как вы должны ввести значение и продолжить, затем добавьте новый double или int и введите write перед retunr (0); scanf_s ("% lf" & переменная);


1
Это вопрос C # .
Вай Ха Ли

-3

Я всегда добавляю следующее заявление в консольное приложение. (Создайте фрагмент кода для этого, если хотите)

Console.WriteLine("Press any key to quit!");
Console.ReadKey();

Это помогает, когда вы хотите экспериментировать с различными концепциями через консольное приложение.

Ctr + F5 заставит консоль остаться, но вы не можете отлаживать! Все консольные приложения, которые я написал в реальном мире, всегда неинтерактивны и запускаются планировщиком, таким как рабочая станция TWS или CA, и не требуют чего-то подобного.


-3

Чтобы упростить то, что говорят другие: используйте Console.ReadKey();.

Это делает так, что программа ждет пользователя, чтобы нажать нормальную клавишу на клавиатуре

Источник: я использую его в своих программах для консольных приложений.


-3

Вы можете решить это очень простым способом, просто вызвав ввод. Однако, если вы нажмете, Enterконсоль снова отключится. Просто используйте это Console.ReadLine();илиConsole.Read();


-4

Добавьте следующее до возврата 0:

system("PAUSE");  

Это печатает строку, чтобы нажать клавишу, чтобы закрыть окно. Это будет держать окно вверх, пока вы не нажмете клавишу ввода. Мои ученики добавили его во все свои программы.


1
вот в с ++
Гонсалу Гарридо

-13

Согласно моему беспокойству, если мы хотим стабилизировать ВЫХОД КОНСОЛЬНОГО ПРИЛОЖЕНИЯ, до закрытия вывода отобразится ИСПОЛЬЗОВАНИЕ, метка: после MainMethod и метка goto; до завершения программы

В программе.

например:

static void Main(string[] args)
{
    label:

    // Snippet of code

    goto label;
}

2
Это просто заставит программу плакатов продолжать печатать «Привет, мир!» много раз
ДэвидПостилл

1
Иисус Христос, не знал, что gotoзаявление было даже разрешено в C #.
Ch3shire
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.