【问题标题】:Cannot stop properly all threads in c#无法正确停止 c# 中的所有线程
【发布时间】:2018-07-25 12:08:16
【问题描述】:

我正在 C# 中尝试使用 token 或 thread.abort 停止所有线程,但两者都无法正常工作

                int workerThreads = 1;
                int portThreads = 0;

                ThreadPool.SetMinThreads(workerThreads, portThreads);
                ThreadPool.SetMaxThreads(workerThreads,portThreads);
                foreach (string d in list)
                {
                    var p = d;
                    ThreadPool.QueueUserWorkItem((c) =>
                    {
                        this.checker(p,cts.Token);
                    });
                }`

用 checker 调用的函数构建如下:

    private void checker(string f, object obj)
    {
        try
        {
            CancellationToken token = (CancellationToken)obj;

            if (token.IsCancellationRequested)
            {
                MessageBox.Show("Stopped", "Checker aborted");
                token.ThrowIfCancellationRequested();
                cts = new CancellationTokenSource();
            } //etc main features of fucntion are hidden from here

我想在调用 cts.Cancel(); 时正确停止所有线程;但每次都会出现: Stopped , checker aborted 并且不仅是一次,而且可能会为每个线程进程显示。如何一次显示消息并在同一时刻停止所有线程? 我还想设置一些在处理其他线程之前应该工作的最大线程数。我尝试使用 SetMaxThreads,但这似乎都不起作用。

【问题讨论】:

  • 你为什么要启动一个线程来启动一个新线程?另外,为什么要将线程与 TPL 混合使用?
  • 试图将最大线程数设置为 1 无法达到预期效果,ThreadPool 类会默默地将其增加到处理器内核数。在现代机器上总是超过 1 个。这样做没有意义,只需启动一个 single 线程并让它迭代列表。该循环也是 token.IsCancellationRequested 测试的正确位置,现在它永远不会工作,因为它在线程开始时永远不会正确。

标签: c# multithreading token threadpool


【解决方案1】:

请参阅 cmets 以获取最佳实践建议,因为您在这里所做的并不完全正确,但要实现您的目标,您可以像这样使用标志和锁:

private static object _lock = new object();
private static bool _stoppedNotificationShown = false;
private void checker(string f, object obj)
{
    try
    {
        CancellationToken token = (CancellationToken)obj;

        if (token.IsCancellationRequested)
        {
            lock(_lock) {
                if (!_stoppedNotificationShown) {
                    _stoppedNotificationShown = true;
                    MessageBox.Show("Stopped", "Checker aborted");
                }
            }
            token.ThrowIfCancellationRequested();
            cts = new CancellationTokenSource();
        } //etc main features of fucntion are hidden from here

【讨论】:

  • 我试过了,但线程不会在几秒钟内终止,要停止整个过程至少需要一分钟......我该如何改进?如果我也尝试再次启动相同的进程而不退出线程函数似乎不再工作的程序
  • 首先,您应该更喜欢任务而不是线程。其次,请记住MessageBox.Show 会阻塞线程,直到消息框没有关闭。
  • 消息框只是为了显示会发生什么,它将被删除...如果我想用任务更改它,我必须使用等待和异步功能才能获得相同的结果?真正的问题是,一旦执行了代码,我就无法再次运行相同的代码,我必须关闭并重新打开程序,因为我无法关闭并重新打开线程。如果有解决方案,我将不胜感激。
  • 我正在使用 asynctask 解决(特别是 await Task.WhenAll ),proelem 是我无法使用 task.whenall 发送取消令牌,因为它在继续之前等待所有任务(这就是我想要但取消令牌在任何情况下都应该起作用)。这是最后一个问题,我解决了其他的......
  • 检查herehere
猜你喜欢
  • 2012-03-23
  • 2019-08-09
  • 2017-01-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-06
  • 1970-01-01
相关资源
最近更新 更多