简体   繁体   English

程序在此控制台中写入时在控制台中写入

[英]Writing in the console while program is writing in this console

Is it possible to write something in the console while the program is writing something in this console ? 当程序正在此控制台中编写某些内容时,是否可以在控制台中编写某些内容? It can be useful when you rename, or remove some files, when you do a repetitive action, and the program is writing a lot in the console. 当您重命名或删除一些文件,执行重复操作并且程序在控制台中编写大量内容时,此功能很有用。 Then you will be able to write a command to stop the execution of the repetitive action while the program is continuing to write in the console. 这样,当程序继续在控制台中写入时,您将能够编写命令来停止重复操作。 I think it's not very clear, well I illustrated you this fact with the code which I think the most apt (but I precise that it doesn't work ;) ). 我认为这还不是很清楚,我用最合适的代码向您说明了这一事实(但我想这是行不通的;))。 We have 3 classes. 我们有3个班级。

The main class : 主班:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    class Program
    {
        private static bool m_Write;

        public static bool write
        {
            get { return m_Write; }
            set { m_Write = value; }
        }

        static void Main(string[] args)
        {
            int index = 0;

            Console.ReadLine();

            m_Write = true;

            Reader reader = new Reader();

            while (m_Write)
            {
                index++;

                Writer writer = new Writer(index.ToString());
            }

        }
    }
}

The reading class : 阅读课:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;

namespace ConsoleApplication1
{
    class Reader
    {
        private Thread m_Reading_Thread;
        private string m_text_To_Read;

        public Reader()
        {
            m_Reading_Thread = new Thread(new ThreadStart(Read));
            m_Reading_Thread.Start();
        }

        public void Read()
        {
            m_text_To_Read = Console.ReadLine();

            if (m_text_To_Read == "Stop")
            {
                Program.write = false;
            }
        }
    }
}

And the writing class : 和写作课:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;

namespace ConsoleApplication1
{
    class Writer
    {
        private Thread m_Writing_Thread;
        private string m_Text_To_Write;

        public Writer(string text_To_Write)
        {
            m_Text_To_Write = text_To_Write;

            m_Writing_Thread = new Thread(new ThreadStart(Write));
            m_Writing_Thread.Start();
        }

        public void Write()
        {
            Console.WriteLine(m_Text_To_Write);
        }
    }
}

This isn't nearly as complicated as you're trying to make it. 这并不像您要尝试的那样复杂。 In general there are two ways you can do this. 通常,有两种方法可以执行此操作。 You can start a background thread to do the writing, and have the main thread block on the console waiting for the read, or you can have the main thread writing and have the background thread do the read. 您可以启动后台线程来进行写入,并让控制台上的主线程块等待读取,或者您可以让主线程进行写入并让后台线程来进行读取。 I like the first solution best: 我最喜欢第一个解决方案:

public class Program
{
    private static readonly ManualResetEvent StopWriting = new ManualResetEvent(false);

    private static void Main(string[] args)
    {
        Thread t = new Thread(WriterFunc);
        t.Start();

        string input;
        do
        {
            input = Console.ReadLine();
        } while (input != "stop");

        // Tell the thread to stop writing
        StopWriting.Set();

        // And wait for the thread to exit
        t.Join();
    }

    private static void WriterFunc()
    {
        int index = 0;
        while (!StopWriting.WaitOne(Timeout.Infinite))
        {
            ++index;
            Console.WriteLine(index.ToString());
        }
    }
}

Note that I used a ManualResetEvent here rather than a Boolean flag. 请注意,我在这里使用了ManualResetEvent而不是Boolean标志。 An even better solution would be to use a CancellationToken . 更好的解决方案是使用CancellationToken Using a flag can cause all kinds of interesting problems because the compiler might determine that the variable can't change (it assumes single-threaded access). 使用标志可能会引起各种有趣的问题,因为编译器可能会确定该变量不能更改(它假定为单线程访问)。 Your thread might continue running even after the variable is changed. 即使更改了变量,您的线程也可能继续运行。

If you want the main thread to do the writing, and the background thread to do the reading: 如果您希望主线程进行写入,而后台线程进行读取:

public class Program
{
    private static readonly ManualResetEvent StopWriting = new ManualResetEvent(false);

    private static void Main(string[] args)
    {
        Thread t = new Thread(ReaderFunc);
        t.Start();

        int index = 0;
        while (!StopWriting.WaitOne(Timeout.Infinite))
        {
            ++index;
            Console.WriteLine(index.ToString());
        }

        // Wait for the background thread to exit
        t.Join();
    }

    private static void ReaderFunc()
    {
        string input;
        do
        {
            input = Console.ReadLine();
        } while (input != "stop");

        // Tell the main thread to stop writing
        StopWriting.Set();
    }
}

Something like this would work: 这样的事情会起作用:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            var w = new Writer();
            var r = new Reader();

            while (!r.finish)
            {
                w.enabled = true;
                string k = Console.ReadKey(false).KeyChar.ToString();
                w.enabled = false;

                string line = k + Console.ReadLine();
                r.Read(line);
            }
        }
    }

    class Writer
    {
        public bool enabled = true;

        public Writer()
        {
            var timer = new System.Timers.Timer(1000);
            timer.Elapsed += (a, b) =>
            {
                if(enabled)
                    Console.WriteLine("Test");
            };
            timer.Start();
        }
    }

    class Reader
    {
        public bool finish = false;

        public void Read(string line)
        {
            if (line == "stop")
            {
                finish = true;
            }
        }
    }
}

Don't worry if the Writer writes above what you are typing, the Console.ReadLine() only considers what you have typed. 如果Writer在您输入的内容之上书写,请不要担心,Console.ReadLine()仅考虑您输入的内容。

In the case of a console application, no two threads can write data to the screen at the exact same time. 对于控制台应用程序,没有两个线程可以在同一时间将数据写入屏幕。

AFAIK, in the above answer, the Writes()'s constructor is continuously executed until it finishes running. AFAIK,在上面的答案中,Writes()的构造函数将连续执行,直到完成运行为止。 Then the control will be passed to the Reader(). 然后,该控件将传递给Reader()。 So I don't think that works for what you need. 因此,我认为这并不适合您的需求。 Correct me if I am wrong. 如果我错了,请纠正我。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM