繁体   English   中英

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

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

是否可以通过在 Windows 表单应用程序中单击按钮来停止正在进行的进程?

  1. 例如,假设有 2 个按钮,“开始”和“停止”
  2. 当您按下“开始”时,它将开始一个无限循环,打印从 1 到无穷大的数字。
  3. 当我按“停止”时,该过程应该在那一刻停止。
  4. 但问题是,我不能按“停止”按钮,因为它不允许我,因为有一个正在进行的过程。

有没有办法克服这个问题?

我知道有一个叫做“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();
    }

如果您产生了一个新进程,那么您可以调用 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

如果您已经启动了新线程,则调用 abort 方法来停止线程。

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

当您按下“开始”按钮时,运行和打印数字的代码将在 ui 线程上运行。 (根据您的解释,我假设您所拥有的只是按钮按下事件的消息处理程序,仅此而已。例如:未设置单独的线程。)。

在 ui 线程上运行无限循环意味着您没有更多时间来处理其他消息。 (负责处理 ui 消息的线程卡在无限循环中。)

因此,为了能够按下“停止”按钮,您需要在不同的线程或完全不同的进程中运行具有无限循环的代码。 这就是 Arjun 想要告诉你的。 (如果您希望无限循环中的代码从表单应用程序访问资源,则需要一个线程。[线程在 forms 应用程序进程内。])

请注意:如果您创建一个线程并在该线程内运行您的数字打印代码,这将不是 ui 线程。 因此,您将无法与 forms 控件进行交互,就像您在 ui 线程上一样。 (即:尝试设置 windows.text 以显示您的数字很可能会引发异常。)

编辑1:

如果您需要与 UI 控件交互,从后台任务执行此操作会引发无效操作 -> 非法跨线程异常。 为了克服这一点,

检查Control.InvokeRequired

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

您可以通过提供 CancellationToken 来启动Task ,并在单击停止按钮时取消操作。

该任务将在另一个线程上执行无限循环,并且您的主线程(UI 线程)不应该受到影响并且应该可以访问。

尝试这个:

/*
    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