Чому вікно консолі відразу закривається, як тільки відображається мій вихід?


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

Відповіді:


266

Проблема тут полягає в тому, що їхня програма Hello World з'являється, вона негайно закриється.
чому так?

Бо закінчено. Коли консольні програми завершили виконання та повернення зі свого mainметоду, пов'язане вікно консолі автоматично закриється. Це очікувана поведінка.

Якщо ви хочете тримати його відкритим для налагодження, вам потрібно доручити комп'ютеру чекати натискання клавіші, перш ніж закінчити додаток і закрити вікно.

Console.ReadLineМетод є одним з способів зробити це. Якщо додати цей рядок до кінця коду (безпосередньо перед returnзаявою), програма змусить вас чекати натискання клавіші перед виходом.

Крім того, ви можете запустити додаток без налагоджувача, приєднаного натисканням клавіші Ctrl+ F5зсередини середовища 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 Ще один рядок непотрібного коду збирається у ваш двійковий файл. Я фактично віддаю перевагу такому підходу до препроцесора.
Джоель

@Joel Чому ми взагалі повинні дбати про це сьогодні?
Олексій

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()чекає натискання клавіші
Кріс,

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 2.1. ...
user1073075

@ user1073075: це дивно. Чи працює ця функція для інших цілей?
Влад

Ні. Спробував за допомогою програми .NET Framework console та все ще не працював. (Я встановив VS2019 на іншій машині і там він працює. Можливо, це помилка у VS17 15.9.4)
user1073075

З 2019 року він працює зараз навіть для проектів WPF: pastebin.com/FpAeV0cW . Але вам доведеться встановити .NET Core 3.
Vlad

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();код перед оператором return, інакше це буде недоступний код.

    Console.Read(); 
    return 0; 

перевірте цю консоль.Прочитайте


3

Додати Readметод для відображення результату.

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


0

Програма закривається, як тільки її виконання закінчиться. У цьому випадку, коли ви return 0;. Це очікувана функціональність. Якщо ви хочете побачити вихід, то або запустіть його в терміналі вручну, або встановіть очікування в кінці програми, щоб він залишався відкритим на кілька секунд (використовуючи бібліотеку для нарізки).


0

це відповідь асинхронізації в консольному додатку на C #?

все, що завгодно в консольному додатку, ніколи не використовуйте, awaitа натомість використовуйте theAsyncMethod().GetAwaiter().GetResult();,

приклад

var result = await HttpClientInstance.SendAsync(message);

стає

var result = HttpClientInstance.SendAsync(message).GetAwaiter().GetResult();


-3

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


1
Це C # питання.
Вай Ха Лі

-3

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

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

Це допомагає, коли ви хочете експериментувати з різними поняттями через консольний додаток.

Ctr + F5 дозволить консолі залишитися, але ви не можете налагоджувати! Усі консольні програми, які я написав у реальному світі, завжди не інтерактивні та спрацьовують за допомогою планувальника, такого як TWS або CA Work Station, і не вимагають чогось подібного.


-3

Щоб спростити те, що говорять інші: Використовуйте Console.ReadKey();.

Це робить це так, що програма чекає на користувача, щоб натиснути звичайну клавішу на клавіатурі

Джерело: Я використовую його у своїх програмах для консольних програм.


-3

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


-4

Перед поверненням 0 додайте наступне:

system("PAUSE");  

Це друкує рядок, щоб натиснути клавішу, щоб закрити вікно. Він буде тримати вікно, поки ви не натиснете клавішу введення. У мене мої студенти додають його до всіх своїх програм.


1
Thats знаходиться в c ++
Гонсало Гаррідо

-13

На мою занепокоєння, якщо ми хочемо стабілізувати ВИХІД КОНСОЛЬНОГО ЗАСТОСУВАННЯ, до закриття відображення на дисплеї ВИКОРИСТАННЯ, мітка: після MainMethod та goto label; до закінчення програми

У програмі.

наприклад:

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

    // Snippet of code

    goto label;
}

2
Це просто спричинить програму плакатів продовжувати друкувати "Привіт, світ!" багато разів
DavidPostill

1
Ісусе Христе, не знав, що gotoзаява була навіть дозволена в C #.
Ч3шир
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.