Как получить сигнал Control+D?

Я, вероятно, не использовал бы отдельный процесс для открытия файла. Вместо этого я, вероятно, использовал бы фоновый поток (если бы я думал, что операция собиралась занять много времени и возможный блок поток UI).

private delegate void FileOpenDelegate(string filename);

public void OpenFile(string filename)
{
   FileOpenDelegate fileOpenDelegate = OpenFileAsync;
   AsyncCallback callback = AsyncCompleteMethod;
   fileOpenDelegate.BeginInvoke(filename, callback, state);
}

private void OpenFileAsync(string filename)
{
   // file opening code here, and then do whatever with the file
}

, Конечно, это не хороший рабочий пример (он ничего не возвращает), и я не показал, как UI обновляется (необходимо использовать BeginInvoke на уровне UI, потому что фоновый поток не может обновить поток UI). Но этот подход обычно в том состоит, как я иду об обработке асинхронных операций в .NET.

52
задан Fabrizio 2 September 2017 в 04:15
поделиться

5 ответов

Как уже говорили другие, для обработки Control + D , обрабатывать "конец файла".

Control + D - это часть связи между пользователем и псевдо-файлом, который вы видите как стандартный ввод. Это не означает конкретно «конец файла», но в более общем плане «очистить введенные мной данные». Сброс означает, что любой вызов read () на stdin в вашей программе возвращается с длиной ввода, введенной с момента последнего сброса. Если строка не пуста, ввод становится доступным для вашей программы, хотя пользователь еще не набрал «return». Если строка пуста, то read () возвращает ноль, и это интерпретируется как «конец файла».

Таким образом, при использовании Control + D , чтобы завершить программу, он работает только в начале строки или если вы сделаете это дважды (первый раз для очистки, второй раз для read () , чтобы вернуть ноль).

Попробуйте:

$ cat
foo
   (type Control-D once)
foofoo (read has returned "foo")
   (type Control-D again)
$
78
ответ дан 7 November 2019 в 09:11
поделиться

Ctrl + D не является сигналом, это EOF (конец файла). Он закрывает канал стандартного ввода. Если чтение (STDIN) возвращает 0, это означает, что stdin закрыт, что означает, что Ctrl + D был нажат (при условии, что на другом конце канала есть клавиатура).

25
ответ дан 7 November 2019 в 09:11
поделиться

Минималистичный пример:

#include <unistd.h> 
#include <stdio.h> 
#include <termios.h> 
#include <signal.h> 

void sig_hnd(int sig){ (void)sig; printf("(VINTR)"); }

int main(){
  setvbuf(stdout,NULL,_IONBF,0);

  struct termios old_termios, new_termios;
  tcgetattr(0,&old_termios);

  signal( SIGINT, sig_hnd );

  new_termios             = old_termios;
  new_termios.c_cc[VEOF]  = 3; // ^C
  new_termios.c_cc[VINTR] = 4; // ^D
  tcsetattr(0,TCSANOW,&new_termios);

  char line[256]; int len;
  do{
    len=read(0,line,256); line[len]='\0';
    if( len <0 ) printf("(len: %i)",len);
    if( len==0 ) printf("(VEOF)");
    if( len >0 ){
      if( line[len-1] == 10 ) printf("(line:'%.*s')\n",len-1,line);
      if( line[len-1] != 10 ) printf("(partial line:'%s')",line);
    }
  }while( line[0] != 'q' );

  tcsetattr(0,TCSANOW,&old_termios);
}

Программа меняет символ VEOF (с Ctrl-D) на Ctrl-C и символ VINTR (с Ctrl-C) на Ctrl-D. Если Вы нажмете Ctrl-D, то драйвер терминала отправит SIGINT обработчику сигнала программы.

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

14
ответ дан 7 November 2019 в 09:11
поделиться

Насколько мне известно, Ctrl + D переводится системой в конец стандартного ввода, поэтому ваше приложение не получит никакого сигнала.

Я думаю, что единственный способ перехватить Ctrl + D - это работать напрямую с системным api (например, доступ к tty)

4
ответ дан 7 November 2019 в 09:11
поделиться

Вы можете использовать poll () и следить за POLLHUP на fd # 1, потому что слой TTY преобразует ^ D в EOF.

-1
ответ дан 7 November 2019 в 09:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: