【问题标题】:C# console Abort multiple threadsC# 控制台中止多个线程
【发布时间】:2020-05-04 13:26:12
【问题描述】:

我在控制台版本的链接测试器上工作。 我在多个线程上启动该功能,但无法通过按键取消它们。 知道我该怎么做吗?

try
{
    Thread[] tr = new Thread[Variables.Threads];
    int i = 0;
    while (i < Variables.Threads && Variables.running)
    {
        tr[i] = new Thread(new ThreadStart(Program.Runner));
        i++;
    }
    //Start each thread  
    foreach (Thread x in tr)
    {
        x.Start();
    }
    //Console.ReadKey();  

    Task.Factory.StartNew(() =>
    {
        while (Colorful.Console.ReadKey().Key != ConsoleKey.Escape);
        Variables.running = false;
        foreach (Thread x in tr)
        {
            x.Abort();
        }
        Program.Menu();
    });

}
catch (Exception)
{
}

编辑:当我的线程接近尾声时,我的所有应用程序都不会移动

【问题讨论】:

  • 您如何阻止您的控制台应用程序终止?使用您给定的代码,控制台应用程序将简单地结束,没有什么可以阻止它。
  • 也许您正在寻找这个? while (tr.Any(x =&gt; x.IsAlive)); //等待线程关闭
  • 感谢您的帮助,但我的研究是关于中止而不是等待。我正在尝试通过按键来停止所有线程。
  • 我的意思是等待 abortion 完成,abort 只是发出要中止的线程,但不会立即中止它,所以你可能需要等待它,我建议的代码就是这样做的。跨度>

标签: c# multithreading console break cancellationtokensource


【解决方案1】:

控制台不是开始学习多任务的好环境,更不用说多线程了。我建议学习多任务处理——尤其是多线程处理——是 WindowsForms 应用程序中的 BackgroundWorker。事件队列的主要作用是保持应用程序处于活动状态,而不会阻塞 I/O。虽然 BackgroundWorker 已经过时了,应该从生产代码中删除,但它是非常好的培训轮。

此外,您当前的代码正在吞噬异常,including fatal ones。这是exception handling 的大罪。不要那样做。

归根结底,您只能在不同的代码行之间进行取消检查和进度报告。在这个 BGW 示例中,我的优势是无论如何我都必须编写所有循环 - 因此深度取消检查和进度报告是可行的。但是如果你使用“别人的代码”,很有可能你必须等待一个函数调用返回,然后才能报告和检查。

#region Primenumbers
private void btnPrimStart_Click(object sender, EventArgs e)
{
    if (!bgwPrim.IsBusy)
    {
        //Prepare ProgressBar and Textbox
        int temp = (int)nudPrim.Value;
        pgbPrim.Maximum = temp;
        tbPrim.Text = "";

        //Start processing
        bgwPrim.RunWorkerAsync(temp);
    }
}

private void btnPrimCancel_Click(object sender, EventArgs e)
{
    if (bgwPrim.IsBusy)
    {
        bgwPrim.CancelAsync();
    }
}

private void bgwPrim_DoWork(object sender, DoWorkEventArgs e)
{
    int highestToCheck = (int)e.Argument;
    //Get a reference to the BackgroundWorker running this code
    //for Progress Updates and Cancelation checking
    BackgroundWorker thisWorker = (BackgroundWorker)sender;

    //Create the list that stores the results and is returned by DoWork
    List<int> Primes = new List<int>();


    //Check all uneven numbers between 1 and whatever the user choose as upper limit
    for(int PrimeCandidate=1; PrimeCandidate < highestToCheck; PrimeCandidate+=2)
    {
        //Report progress
        thisWorker.ReportProgress(PrimeCandidate);
        bool isNoPrime = false;

        //Check if the Cancelation was requested during the last loop
        if (thisWorker.CancellationPending)
        {
            //Tell the Backgroundworker you are canceling and exit the for-loop
            e.Cancel = true;
            break;
        }

        //Determin if this is a Prime Number
        for (int j = 3; j < PrimeCandidate && !isNoPrime; j += 2)
        {
            if (PrimeCandidate % j == 0)
                isNoPrime = true;
        }

        if (!isNoPrime)
            Primes.Add(PrimeCandidate);
    }

    //Tell the progress bar you are finished
    thisWorker.ReportProgress(highestToCheck);

    //Save Return Value
    e.Result = Primes.ToArray();
}

private void bgwPrim_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    pgbPrim.Value = e.ProgressPercentage;
}

private void bgwPrim_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    pgbPrim.Value = pgbPrim.Maximum;
    this.Refresh();

    if (!e.Cancelled && e.Error == null)
    {
        //Show the Result
        int[] Primes = (int[])e.Result;

        StringBuilder sbOutput = new StringBuilder();

        foreach (int Prim in Primes)
        {
            sbOutput.Append(Prim.ToString() + Environment.NewLine);
        }

        tbPrim.Text = sbOutput.ToString();
    }
    else 
    {
        tbPrim.Text = "Operation canceled by user or Exception";
    }
}
#endregion

但是,在您的情况下,多线程 似乎并不重要。多tasking 没有线程可能会更好。线程仅在您有 CPU 限制 任务时才有帮助。 “检查链接”听起来像是一个网络绑定任务。线程有一些额外的麻烦,你最好避免。

【讨论】:

  • 感谢您提供所有信息。我已经在 UI 应用程序中使用了 BackgroundWorker,但我希望找到一种控制台模式的方法。您有将我的线程方法转换为多任务处理的示例吗?对不起,我在这个地方比较新手^^'
  • @hackhacky 一个问题是保持应用程序处于活动状态,但不会阻塞 I/O。为此,GUI 事件循环简直是完美的。没有它,您必须复制该功能。 |对于多任务处理,我只能为您指出 async/await 教程。它导致编译器和运行时处理大量管道:docs.microsoft.com/en-us/dotnet/visual-basic/programming-guide/…
  • 再次感谢老兄,要检查一下
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多