【问题标题】:How close the Thread opening after it ends?线程结束后如何关闭线程开口?
【发布时间】:2013-08-03 12:51:42
【问题描述】:

我想知道在我的函数结束后如何中止我的线程Thread.Abort();
我的应用程序运行文件和打开的每个文件都是不同的线程

int _counter;
int _parallelThreads
_queue = new Queue();

public void transmit()
{
    while (_counter < _parallelThreads)
    {
        lock (_queue)
        {
            string file = (string)_queue.Dequeue();
            ThreadStart ts = delegate { processFile(file); };
            Thread thread = new Thread(ts);
            thread.IsBackground = true;
            thread.Start();
            _counter++;
        }
    }
}

private void processFile(string file)
{
    WiresharkFile wf = new WiresharkFile(file, _selectedOutputDevice, 1);
    wf.OnFinishPlayEvent += wf_OnFinishPlayEvent;
    wf.sendBuffer();
}

这是我的文件完成的事件

private void wf_OnFinishPlayEvent(MyClass class)
{
   // here i want to abort my thread
}

我想在线程完成后中止线程的原因是因为我认为这是我的内存不足的原因,以防我打开很多并行线程并反复运行它(我的应用程序内存使用量读取超过 1 giga)

【问题讨论】:

  • 你真的不应该中止线程。通过检查标志或其他方式,提供一种在不再需要时优雅地退出它们的方法。
  • 为什么中止线程是个坏主意?像你建议的那样中止和退出有什么区别?
  • This answer 很好地解释了 Thread.Abort() 的核心问题。
  • _parallelThreads 的值是多少?
  • 同时打开多少个线程,但我内存不足,我知道因为我打开了所有线程

标签: c# winforms


【解决方案1】:

当你中止一个线程时,很多意想不到的事情可能会出错。特别是当您处理文件时。当我不得不这样做时(例如,“取消”按钮),我使用了一个小技巧。

我有一个标志IsCanceled 在两个线程都可以看到的范围内设置为true,并且在工作线程上,每隔几条语句就会检查该标志并关闭所有打开的文件并自行结束。

这可能不适用于您的情况,具体取决于wf.sendBuffer(); 逻辑。告诉我

例子:

private void processFile(string file)
{
    WiresharkFile wf = new WiresharkFile(file, _selectedOutputDevice, 1);
    wf.OnFinishPlayEvent += wf_OnFinishPlayEvent;

    if(IsCanceled == false)
    {
       wf.sendBuffer();
    }
}

如果sendBuffer()方法逻辑太长,那么

public void sendBuffer()
{
    // some logic

    if(IsCanceled)
    {
       // close open streams
       return;
    }

    // some logic
}

至于标志本身,单例类可以做到这一点,或者所有其他类都知道的类

public class Singleton
{
   private static Singleton instance;
   private bool isCanceled;
   private Singleton() 
   {
       isCanceled = false;
   }

   public static Singleton Instance
   {
      get 
      {
         if (instance == null)
         {
            instance = new Singleton();
         }
         return instance;
      }
   }

   public bool IsCanceled
   {
      get 
      {
         return isCanceled;
      }
      set
      {
         isCanceled = value;
      }
   }
}

请注意,单例类对所有人开放,您可能希望使用只有需要检查它的线程知道的类。这取决于您的安全需求。

【讨论】:

  • @user2214609 当然,等一下
  • @user2214609 让我知道你的想法
  • IsCanceled 变量在我的类中放在哪里?
  • 你能解释一下如何使用 Singleton 类以及为什么它的构造函数是私有的吗?
  • @user2214609 你可以在这里阅读单身人士 - en.wikipedia.org/wiki/Singleton_pattern
【解决方案2】:

您不应该中止线程,线程将在其中的代码完成时自动退出。也许您只是想等待线程完成,然后执行其他操作。
您可以使用数组来存储线程,并使用 Thread.Join() 等待所有线程结束。

List<Thread> threadList = new List<Thread>();

public void transmit()
{
    while (_counter < _parallelThreads)
    {
        lock (_queue)
        {
            string file = (string)_queue.Dequeue();
            ThreadStart ts = delegate { processFile(file); };
            Thread thread = new Thread(ts);
            thread.IsBackground = true;        
            threadList.Add(thread);       //add thread to list
            thread.Start();
            _counter++;
        }
    }
    //wait threads to end
    foreach(Thread t in threadList)
          t.Join();
}

private void processFile(string file)
{
    WiresharkFile wf = new WiresharkFile(file, _selectedOutputDevice, 1);
    wf.OnFinishPlayEvent += wf_OnFinishPlayEvent;
    wf.sendBuffer();
}

【讨论】:

  • 因为 t.Join();它甚至还没有开始播放
  • 在for语句中,下面这行代码会启动线程。
    thread.Start();无论您是否编写 t.Join() 都不会影响线程的执行。如果只写thread.Start(),线程就会启动。不管你写不写thread.Joion。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-05
  • 2018-10-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多