简体   繁体   English

C# 表单应用程序 - 单击另一个按钮即可停止正在进行的进程

[英]C# Form Application - Stop an ongoing process with a click of another button

Is it possible to stop an ongoing process with a button click in Windows form application?是否可以通过在 Windows 表单应用程序中单击按钮来停止正在进行的进程?

  1. For example, let's say there are 2 buttons, "START" and "STOP"例如,假设有 2 个按钮,“开始”和“停止”
  2. When you press "START", it will start an infinite loop, printing numbers from 1 to infinity.当您按下“开始”时,它将开始一个无限循环,打印从 1 到无穷大的数字。
  3. When I press "STOP", the process should stop at that moment.当我按“停止”时,该过程应该在那一刻停止。
  4. But the problem is, I cannot press the "STOP" button as it does not allow me, since there's an ongoing process.但问题是,我不能按“停止”按钮,因为它不允许我,因为有一个正在进行的过程。

Is there a way to overcome this?有没有办法克服这个问题?

I know there's something called "MethodInvoker", but I have no idea how that works or whether it is relevant to this.我知道有一个叫做“MethodInvoker”的东西,但我不知道它是如何工作的,也不知道它是否与此相关。

    private bool keepRunning = true;

    public Form1()
    {
        InitializeComponent();
    }

    private void StartBtn_Click(object sender, EventArgs e)
    {
        var number = 1;
        while (keepRunning)
        {
            Thread.Sleep(1000);
            MesgeLabel.Text = "" + number++;
        }
    }

    private void StopBtn_Click(object sender, EventArgs e)
    {
        //Cannot even click this button
        keepRunning = false;
        //or
        Application.Exit();
    }

If you have spawned a new process then you can call kill method.如果您产生了一个新进程,那么您可以调用 kill 方法。

Process myProcess = Process.Start("Notepad.exe")//starts new process
myProcess.Kill();// kills the process. save reference to myProcess and call kill on STOP button click

If you have started new thread then call abort method to stop the thread.如果您已经启动了新线程,则调用 abort 方法来停止线程。

Thread thread = new Thread(new ThreadStart(method)); 
thread.Start(); 
thread.Abort(); // terminates the thread. call abort on STOP button click

When you press the "start" button, the code that runs and prints the numbers will run on the ui thread.当您按下“开始”按钮时,运行和打印数字的代码将在 ui 线程上运行。 (from your explanation, i assume that all you have is the message handler for the button press event and nothing else. eg: Not setting up a seperate thread.). (根据您的解释,我假设您所拥有的只是按钮按下事件的消息处理程序,仅此而已。例如:未设置单独的线程。)。

Running an infinite loop on the ui thread means, that you do not get any more time for processing other messages.在 ui 线程上运行无限循环意味着您没有更多时间来处理其他消息。 (the thread that is responsible for processing the ui messages is stuck in your infinite loop.) (负责处理 ui 消息的线程卡在无限循环中。)

So, in order to be able to press the "stop" button, you need to run the code with the infinite loop in a different thread or in a different process altogether.因此,为了能够按下“停止”按钮,您需要在不同的线程或完全不同的进程中运行具有无限循环的代码。 This is what Arjun is trying to tell you.这就是 Arjun 想要告诉你的。 (if you want the code in the infinite loop to access resources from your form app, you need a thread. [the thread is inside the forms app process.]) (如果您希望无限循环中的代码从表单应用程序访问资源,则需要一个线程。[线程在 forms 应用程序进程内。])

please note: if you create a thread and run your number printing code inside that thread, this will not be the ui thread.请注意:如果您创建一个线程并在该线程内运行您的数字打印代码,这将不是 ui 线程。 Thus, you will not be able to interact with the forms controls as if you'd be on the ui thread.因此,您将无法与 forms 控件进行交互,就像您在 ui 线程上一样。 (ie: trying to set the windows.text in order to display your numbers will most likely throw an exception.) (即:尝试设置 windows.text 以显示您的数字很可能会引发异常。)

EDIT 1:编辑1:

If you need to interact with UI controls, doing it from a background task would throw invalid operation -> illegal cross thread exception.如果您需要与 UI 控件交互,从后台任务执行此操作会引发无效操作 -> 非法跨线程异常。 To overcome this,为了克服这一点,

check Control.InvokeRequired检查Control.InvokeRequired

if(myLabel.InvokeRequired)
    myLabel.Invoke(new Action(() => myLabel.Text = newText));
else
    myLabel.Text = newText;

You can start a Task by providing a CancellationToken and cancel the operation when the stop button is clicked.您可以通过提供 CancellationToken 来启动Task ,并在单击停止按钮时取消操作。

The task will execute the infinite loop on another thread and your main thread (the UI thread) should not be affected and should be accessible.该任务将在另一个线程上执行无限循环,并且您的主线程(UI 线程)不应该受到影响并且应该可以访问。

Try this:尝试这个:

/*
    Please add these on top of your form class

    using System.Diagnostics;
    using System.Threading;
    using System.Threading.Tasks;
*/

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    CancellationTokenSource cancellationTokenSource;
    CancellationToken cancellationToken;

    private void CountToInfinity()
    {
        while (true)
        {
            cancellationToken.ThrowIfCancellationRequested();

            Debug.WriteLine(new Random().Next());
        }
    }

    private async void button1_Click(object sender, EventArgs e)
    {
        if (cancellationTokenSource == null)
        {
            cancellationTokenSource = new CancellationTokenSource();
            cancellationToken = cancellationTokenSource.Token;
            Task.Run((Action)CountToInfinity, cancellationToken);
        }
    }

    private void button2_Click(object sender, EventArgs e)
    {
        if (cancellationTokenSource != null)
        {
            cancellationTokenSource.Cancel();
            cancellationTokenSource.Dispose();
            cancellationTokenSource = null;
        }
    }


}

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

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